﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using XmlStudio.DataLayer;
using XmlStudio.Enums;
using XmlStudio.Interfaces;
using XmlStudio.Models;
using XmlStudio.Utilities;
using System.Xml.XPath;
using GojiSoft.EventSequenceUnitTesting;
using XmlStudio.Models.Actions;

namespace XmlStudio.Tests {
    /// <summary>
    ///This is a test class for XmlModelTest and is intended
    ///to contain all XmlModelTest Unit Tests.
    ///</summary>
    [TestClass()]
    public class XmlModelTest {
        #region Fields
        private TestContext testContextInstance;
        #endregion

        #region Properties
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext {
            get {
                return testContextInstance;
            }
            set {
                testContextInstance = value;
            }
        }
        #endregion

        #region Additional test simpleTypes
        // 
        //You can use the following additional simpleTypes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region GetRootElement tests
        /// <summary>
        ///A test for GetRootElement.
        ///</summary>
        [TestMethod()]
        public void GetRootElementTest01() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            BigXmlNode root = model.GetRootElement();

            Assert.IsNotNull(root);
            Assert.AreEqual<string>("root", root.Name);
            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Collapsed);
        }

        /// <summary>
        /// A test for GetRootElement on file with no root element. Should return null.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void GetRootElementTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest3);
            BigXmlNode root = model.GetRootElement();

            Assert.IsNull(root);
            Assert.IsFalse(root.Modified);
        }

        [TestMethod()]
        public void GetRootElementTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            BigXmlNode root = model.GetRootElement();
            Assert.IsFalse(root.Modified);

            model.Undo();
        }

        /// <summary>
        /// Tests for events raised during GetRootElemenet()
        /// </summary>
        [TestMethod()]
        public void GetRootElementTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            Action test = () => { model.GetRootElement(); };
            var expectedSequence = new[] { "RootElementAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod()]
        public void GetRootElementEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            Action test = () => {
                var root = model.GetRootElement();
            };

            var expectedSequence = new[] { "RootElementAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region ExpandElementAction tests
        /// <summary>
        /// Tests the ExpandElementAction.
        /// </summary>
        [TestMethod()]
        public void ExpandElementActionTest01() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            var root = model.GetRootElement();
            var rootInternal = root as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(rootInternal.XmlNode.ChildNodes.Count == 0);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.IsTrue(root.ChildNodes.Count == 2);
            Assert.IsTrue(((XmlNode)rootInternal.XmlNode).ChildNodes.Count == 2);
            BigXmlNode childNode1 = root.ChildNodes[0];
            BigXmlNode childNode2 = root.ChildNodes[1];

            Assert.IsNotNull(childNode1);
            Assert.IsNotNull(childNode2);
            Assert.IsTrue(childNode1.Parent == root);
            Assert.IsTrue(childNode2.Parent == root);
        }

        /// <summary>
        /// Tests the ExpandElementAction.
        /// </summary>
        [TestMethod()]
        public void ExpandElementActionTest02() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, "1");

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.PartiallyExpanded);
            Assert.IsTrue((from x in root.ChildNodes where x != null select x).Count() == 1);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 1);
            var childNode1 = root.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsNotNull(childNode1);

            Assert.IsTrue(childNode1.Parent == root);
            Assert.IsTrue(((XmlNode)childNode1.XmlNode).ParentNode == root.XmlNode);
        }

        /// <summary>
        /// Tests the ExpandElementAction and undo.
        /// Update: undo not supported for Expand.
        /// </summary>
        [TestMethod()]
        public void ExpandElementActionTest03() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, "1");

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.PartiallyExpanded);
            Assert.AreEqual<int>(1, (from x in root.ChildNodes where x != null select x).Count());
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 1);
            var childNode1 = root.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsNotNull(childNode1);

            Assert.IsTrue(childNode1.Parent == root);
            Assert.IsTrue(((XmlNode)childNode1.XmlNode).ParentNode == root.XmlNode);
        }

        /// <summary>
        /// Tests the ExpandElementAction, multiple times.
        /// </summary>
        [TestMethod()]
        public void ExpandElementActionTest04() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            // Assert.AreEqual<string>(string.Empty, root.ExpandedRange);
            Assert.IsTrue(root.ChildNodes.Count == 2);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 2);

            var childNode1 = root.ChildNodes[0] as BigXmlNodeInternal;
            var childNode2 = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsNotNull(childNode1);
            Assert.IsNotNull(childNode2);

            Assert.IsTrue(childNode1.Parent == root);
            Assert.IsTrue(((XmlNode)childNode1.XmlNode).ParentNode == root.XmlNode);

            Assert.IsTrue(childNode2.Parent == root);
            Assert.IsTrue(((XmlNode)childNode2.XmlNode).ParentNode == root.XmlNode);

            Assert.IsTrue(childNode1.NodeState == ExpandState.Collapsed);
            Assert.IsTrue(childNode2.NodeState == ExpandState.Collapsed);

            model.ExpandNode(childNode1, string.Empty);
            model.ExpandNode(childNode2, string.Empty);

            Assert.IsFalse(childNode1.Modified);
            Assert.IsFalse(childNode2.Modified);

            Assert.IsTrue(childNode1.NodeState == ExpandState.Expanded);
            Assert.IsTrue(childNode2.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(2, childNode1.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)childNode1.XmlNode).ChildNodes.Count);

            Assert.AreEqual<int>(2, childNode2.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)childNode1.XmlNode).ChildNodes.Count);
        }

        /// <summary>
        /// Tests the ExpandElementAction, multiple times with undo.
        /// Update: undo is not supported for Expand.
        /// </summary>
        [TestMethod()]
        public void ExpandElementActionTest05() {
            var model = ModelFactory.CreateXmlModel(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.IsTrue(root.ChildNodes.Count == 2);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 2);

            var childNode1 = root.ChildNodes[0] as BigXmlNodeInternal;
            var childNode2 = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsNotNull(childNode1);
            Assert.IsNotNull(childNode2);

            Assert.IsTrue(childNode1.Parent == root);
            Assert.IsTrue(((XmlNode)childNode1.XmlNode).ParentNode == root.XmlNode);

            Assert.IsTrue(childNode2.Parent == root);
            Assert.IsTrue(((XmlNode)childNode2.XmlNode).ParentNode == root.XmlNode);

            Assert.IsTrue(childNode1.NodeState == ExpandState.Collapsed);
            Assert.IsTrue(childNode2.NodeState == ExpandState.Collapsed);

            model.ExpandNode(childNode1, string.Empty);
            model.ExpandNode(childNode2, string.Empty);

            Assert.IsFalse(childNode1.Modified);
            Assert.IsFalse(childNode2.Modified);
            Assert.IsTrue(childNode1.NodeState == ExpandState.Expanded);
            Assert.IsTrue(childNode2.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(2, childNode1.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)childNode1.XmlNode).ChildNodes.Count);

            Assert.AreEqual<int>(2, childNode2.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)childNode2.XmlNode).ChildNodes.Count);
        }

        /// <summary>
        /// Test for ExpandNodeAction. Tests for Nodes property.
        /// </summary>
        [TestMethod()]
        public void ExpandNodeActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            // Assert.IsTrue(xmlModel.Nodes.Contains(new KeyValuePair<int[], BigXmlNode>(root.Address, root)));
            Assert.IsNotNull(root);
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            Assert.IsNotNull(categories);
            Assert.IsNotNull(stock);
            //Assert.IsTrue(xmlModel.Nodes.Contains(new KeyValuePair<int[], BigXmlNode>(categories.Address, categories)));
            //Assert.IsTrue(xmlModel.Nodes.Contains(new KeyValuePair<int[], BigXmlNode>(stock.Address, stock)));
        }

        /// <summary>
        /// Test for multiple partial expansion.
        /// </summary>
        [TestMethod()]
        public void ExpandNodeActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);
            var stock = root.ChildNodes[1];

            model.ExpandNode(stock, "2"); // get only cds
            var cds = stock.ChildNodes[1];

            Assert.AreEqual<int>(1, (from x in stock.ChildNodes where x != null select x).Count());
            Assert.IsTrue(stock.NodeState == ExpandState.PartiallyExpanded);
            Assert.IsTrue(cds.Address.SequenceEqual(new int[] { 1, 2, 2 }));

            model.ExpandNode(stock, "1");

            Assert.IsTrue(stock.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(2, (from x in stock.ChildNodes where x != null select x).Count());

            var books = stock.ChildNodes[0];
            cds = stock.ChildNodes[1];

            Assert.IsTrue(books.Address.SequenceEqual(new int[] { 1, 2, 1 }));
            Assert.IsTrue(cds.Address.SequenceEqual(new int[] { 1, 2, 2 }));

            //xmlModel.Undo();

            //cds = stock.ChildNodes[1];

            //Assert.AreEqual<int>(1, (from x in stock.ChildNodes where x != null select x).Count());
            //Assert.IsTrue(stock.NodeState == ExpandState.PartiallyExpanded);
            //Assert.IsTrue(cds.Address.SequenceEqual(new int[] { 1, 2, 2 }));
        }

        /// <summary>
        /// Test for ExpandNodeAction, partial expansion, test for childNodes collection
        /// being of a correct size.
        /// </summary>
        [TestMethod()]
        public void ExpandNodeActiontest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest6);

            var root = model.GetRootElement();
            model.ExpandNode(root, "2-4");

            Assert.AreEqual<int>(5, root.TotalChildCount);
            Assert.AreEqual<int>(5, root.ChildNodes.Count);
        }

        /// <summary>
        /// Test for element expansion. Checks child counts and partial expansions.
        /// </summary>
        [TestMethod()]
        public void ExpandElementTest01() {
            const int oldTestamentChildCount = 39;
            const int newTestamentChildCount = 27;

            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement();
            Assert.IsNotNull(root);
            //Assert.AreEqual<int>(1, xmlModel.Nodes.Keys.Count);
            //Assert.IsTrue(xmlModel.Nodes[root.Address] == root);

            model.ExpandNode(root, string.Empty);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            Assert.IsNotNull(oldTestament);
            Assert.IsNotNull(newTestament);
            // check Nodes
            //Assert.AreEqual<int>(3, xmlModel.Nodes.Keys.Count);
            //Assert.IsTrue(xmlModel.Nodes[oldTestament.Address] == oldTestament);
            //Assert.IsTrue(xmlModel.Nodes[newTestament.Address] == newTestament);

            // check child counts
            Assert.AreEqual<int>(oldTestamentChildCount, oldTestament.TotalChildCount);
            Assert.AreEqual<int>(newTestamentChildCount, newTestament.TotalChildCount);

            model.ExpandNode(oldTestament, "3-5");

            Assert.AreEqual<ExpandState>(ExpandState.PartiallyExpanded, oldTestament.NodeState);

            // check that oldTestament has collection of child elements of lenght equal to TotalChildCount
            // but filled only with 3 not null nodes
            Assert.AreEqual<int>(oldTestamentChildCount, oldTestament.ChildNodes.Count);
            Assert.AreEqual<int>(3, (from i in oldTestament.ChildNodes where i != null select i).Count());

            var book3 = oldTestament.ChildNodes[2];
            var book4 = oldTestament.ChildNodes[3];
            var book5 = oldTestament.ChildNodes[4];

            Assert.IsNotNull(book3);
            Assert.IsNotNull(book4);
            Assert.IsNotNull(book5);

            // check Nodes
            //Assert.AreEqual<int>(6, xmlModel.Nodes.Keys.Count);
            //Assert.IsTrue(xmlModel.Nodes[book3.Address] == book3);
            //Assert.IsTrue(xmlModel.Nodes[book4.Address] == book4);
            //Assert.IsTrue(xmlModel.Nodes[book5.Address] == book5);

            Assert.IsTrue(oldTestament.ExpandedRange.SequenceEqual(new int[] { 3, 4, 5 }));

            // expand some more nodes

            model.ExpandNode(oldTestament, "7-8");

            Assert.AreEqual<ExpandState>(ExpandState.PartiallyExpanded, oldTestament.NodeState);
            Assert.AreEqual<int>(oldTestamentChildCount, oldTestament.ChildNodes.Count);
            Assert.AreEqual<int>(5, (from i in oldTestament.ChildNodes where i != null select i).Count());

            var book7 = oldTestament.ChildNodes[6];
            var book8 = oldTestament.ChildNodes[7];

            Assert.IsNotNull(book7);
            Assert.IsNotNull(book8);

            // check Nodes
            //Assert.AreEqual<int>(8, xmlModel.Nodes.Keys.Count);
            //Assert.IsTrue(xmlModel.Nodes[book7.Address] == book7);
            //Assert.IsTrue(xmlModel.Nodes[book8.Address] == book8);

            Assert.IsTrue(oldTestament.ExpandedRange.SequenceEqual(new int[] { 3, 4, 5, 7, 8 }));

            // expand some more but with overlap
            model.ExpandNode(oldTestament, "4-8");

            Assert.AreEqual<ExpandState>(ExpandState.PartiallyExpanded, oldTestament.NodeState);
            Assert.AreEqual<int>(oldTestamentChildCount, oldTestament.ChildNodes.Count);
            Assert.AreEqual<int>(6, (from i in oldTestament.ChildNodes where i != null select i).Count());

            var book6 = oldTestament.ChildNodes[5];
            Assert.IsNotNull(book6);

            // check Nodes
            //Assert.AreEqual<int>(9, xmlModel.Nodes.Keys.Count);
            //Assert.IsTrue(xmlModel.Nodes[book6.Address] == book6);

            Assert.IsTrue(oldTestament.ExpandedRange.SequenceEqual(new int[] { 3, 4, 5, 6, 7, 8 }));

            model.CollapseNode(oldTestament);

            Assert.AreEqual<ExpandState>(ExpandState.Collapsed, oldTestament.NodeState);
            // Assert.AreEqual<int>(3, xmlModel.Nodes.Keys.Count);
            Assert.AreEqual<int>(39, oldTestament.ChildNodes.Count);
            Assert.AreEqual<int>(0, (from i in oldTestament.ChildNodes where i != null select i).Count());

            model.ExpandNode(oldTestament);

            Assert.AreEqual<ExpandState>(ExpandState.Expanded, oldTestament.NodeState);
            // Assert.AreEqual<int>(oldTestamentChildCount + 3, xmlModel.Nodes.Keys.Count);
            Assert.AreEqual<int>(oldTestamentChildCount, oldTestament.ChildNodes.Count);
            Assert.AreEqual<int>(oldTestamentChildCount, (from i in oldTestament.ChildNodes where i != null select i).Count());
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ExpandElementTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest8);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            var dvds = stock.ChildNodes[2];

            model.ExpandNode(dvds);
            var dvd2 = dvds.ChildNodes[1];

            Assert.AreEqual<int>(0, dvd2.TotalChildCount);
            Assert.AreEqual<ExpandState>(ExpandState.Expanded, dvd2.NodeState);

            model.ExpandNode(dvd2);
            Assert.AreEqual<int>(0, dvd2.TotalChildCount);
            Assert.AreEqual<ExpandState>(ExpandState.Expanded, dvd2.NodeState);
        }

        [TestMethod()]
        public void ExpandElementEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            Action test = () => {
                model.ExpandNode(root);
            };

            var expectedSequence = new[] { "NodeExpanded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region Build new document tests
        [TestMethod()]
        public void BuildNewDocumentTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.CreateRootElement("root");

            var root = model.GetRootElement();

            Assert.IsNotNull(root);

            var child1 = model.CreateElement("child1");
            var child2 = model.CreateElement("child2");
            var child3 = model.CreateElement("child3");

            Assert.IsNotNull(child1);
            Assert.IsNotNull(child2);
            Assert.IsNotNull(child3);

            Assert.AreEqual<string>("child1", child1.Name);
            Assert.AreEqual<string>("child2", child2.Name);
            Assert.AreEqual<string>("child3", child3.Name);

            model.AddChildNode(root, child1, InsertMode.Last, null);
            model.AddChildNode(root, child2, InsertMode.Last, null);
            model.AddChildNode(root, child3, InsertMode.Last, null);

            Assert.AreEqual<int>(3, root.ChildNodes.Count);
        }
        #endregion

        #region CollapseNodeAction tests
        /// <summary>
        /// CollapseNodeAction test.
        /// </summary>
        [TestMethod()]
        public void CollapseNodeActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.AreEqual<int>(2, root.TotalChildCount);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(2, ((XmlNode)root.XmlNode).ChildNodes.Count);

            model.CollapseNode(root);

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)root.XmlNode).ChildNodes.Count);
        }

        /// <summary>
        /// CollapseNodeAction test.
        /// </summary>
        [TestMethod()]
        public void CollapseNodeActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)root.XmlNode).ChildNodes.Count);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);

            var node1 = root.ChildNodes[0] as BigXmlNodeInternal;
            var node2 = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);

            model.ExpandNode(node1, string.Empty);
            model.ExpandNode(node2, string.Empty);

            Assert.IsFalse(node1.Modified);
            Assert.IsFalse(node2.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Expanded);
            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(2, node1.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.AreEqual<int>(2, node2.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node1);

            Assert.IsFalse(node1.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(2, node2.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node2);

            Assert.IsFalse(node2.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, node2.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node2.XmlNode).ChildNodes.Count);
        }

        /// <summary>
        /// CollapseNodeAction test.
        /// </summary>
        [TestMethod()]
        public void CollapseNodeActionTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.IsTrue(root.ChildNodes.Count == 2);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)root.XmlNode).ChildNodes.Count);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);

            var node1 = root.ChildNodes[0] as BigXmlNodeInternal;
            var node2 = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);

            model.ExpandNode(node1, string.Empty);
            model.ExpandNode(node2, string.Empty);

            Assert.IsFalse(node1.Modified);
            Assert.IsFalse(node2.Modified);

            Assert.IsTrue(node1.NodeState == ExpandState.Expanded);
            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(39, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(27, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node1);

            Assert.IsFalse(node1.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsFalse(node2.Modified);
            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(27, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node2);

            Assert.IsFalse(node1.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node2.XmlNode).ChildNodes.Count);
        }

        /// <summary>
        /// CollapseNodeAction test with undo.
        /// Update: undo is no longer supported for Collapse.
        /// </summary>
        [TestMethod()]
        public void CollapseNodeActionWithUndoTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);
            Assert.IsTrue(root.ChildNodes.Count == 2);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes.Count == 0);

            model.ExpandNode(root, string.Empty);

            Assert.IsFalse(root.Modified);
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
            Assert.AreEqual<int>(2, ((XmlNode)root.XmlNode).ChildNodes.Count);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);

            var node1 = root.ChildNodes[0] as BigXmlNodeInternal;
            var node2 = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);

            model.ExpandNode(node1, string.Empty);
            model.ExpandNode(node2, string.Empty);

            Assert.IsFalse(node1.Modified);
            Assert.IsFalse(node2.Modified);

            Assert.IsTrue(node1.NodeState == ExpandState.Expanded);
            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(39, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(27, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node1);

            Assert.IsFalse(node1.Modified);

            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsTrue(node2.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(27, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            model.CollapseNode(node2);

            Assert.IsFalse(node2.Modified);
            Assert.IsTrue(node1.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(39, node1.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node1.XmlNode).ChildNodes.Count);

            Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            Assert.AreEqual<int>(0, ((XmlNode)node2.XmlNode).ChildNodes.Count);

            //xmlModel.Undo();

            //Assert.IsFalse(node2.Modified);
            //Assert.IsTrue(node2.NodeState == ExpandState.Expanded);
            //Assert.AreEqual<int>(27, node2.ChildNodes.Count);
            //Assert.AreEqual<int>(27, node2.XmlNode.ChildNodes.Count);

            //xmlModel.CollapseNode(node2);
            //xmlModel.ExpandNode(node2, "1-10");

            //Assert.IsFalse(node2.Modified);

            //Assert.IsTrue(node2.NodeState == ExpandState.PartiallyExpanded);
            //Assert.AreEqual<int>(10, (from x in node2.ChildNodes where x != null select x).Count());
            //Assert.AreEqual<int>(10, node2.XmlNode.ChildNodes.Count);

            //xmlModel.CollapseNode(node2);

            //Assert.IsFalse(node2.Modified);
            //Assert.IsTrue(node2.NodeState == ExpandState.Collapsed);
            //Assert.AreEqual<int>(0, node2.ChildNodes.Count);
            //Assert.AreEqual<int>(0, node2.XmlNode.ChildNodes.Count);

            //xmlModel.Undo();

            //Assert.IsFalse(node2.Modified);
            //Assert.IsTrue(node2.NodeState == ExpandState.PartiallyExpanded);
            //Assert.AreEqual<int>(10, (from x in node2.ChildNodes where x != null select x).Count());
            //Assert.AreEqual<int>(10, node2.XmlNode.ChildNodes.Count);
        }

        /// <summary>
        /// Test for collapse when expanding some nodes and then collapsing the root.
        /// </summary>
        [TestMethod()]
        public void CollapseNodeActionTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ExpandNode(oldTestament);
            model.ExpandNode(newTestament);

            // Assert.IsTrue(xmlModel.Nodes.Keys.Count > 3);

            model.CollapseNode(root);
            // Assert.IsTrue(xmlModel.Nodes.Count == 1);
        }

        [TestMethod()]
        public void CollapseNodeEventsTest() {
            var model = new XmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);

            Action test = () => {
                model.CollapseNode(root);
            };

            var expectedSequence = new[] { "NodeCollapsed", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region RenameElementAction tests
        /// <summary>
        /// RenameElementAction test.
        /// </summary>
        [TestMethod()]
        public void RenameElementActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);

            model.ExpandNode(root, string.Empty);
            var oldTestament = root.ChildNodes[0] as BigXmlNodeInternal;
            var newTestament = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsNotNull(oldTestament);
            model.RenameElement(oldTestament, "oldTestament");

            Assert.IsTrue(model.Modified);
            model.RenameElement(newTestament, "newTestament");

            Assert.IsTrue(oldTestament.Modified);
            Assert.IsTrue(newTestament.Modified);

            Assert.AreEqual<string>("oldTestament", oldTestament.LocalName);
            Assert.AreEqual<string>("newTestament", newTestament.LocalName);
        }

        /// <summary>
        /// RenameElementAction test with undo and redo.
        /// </summary>
        [TestMethod()]
        public void RenameElementActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);

            model.ExpandNode(root, string.Empty);
            var oldTestament = root.ChildNodes[0] as BigXmlNodeInternal;
            var newTestament = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.IsNotNull(oldTestament);
            model.RenameElement(oldTestament, "oldTestament");
            model.RenameElement(newTestament, "newTestament");

            Assert.IsTrue(oldTestament.Modified);
            Assert.IsTrue(newTestament.Modified);

            Assert.AreEqual<string>("oldTestament", oldTestament.LocalName);
            Assert.AreEqual<string>("newTestament", newTestament.LocalName);

            model.Undo();

            Assert.AreEqual<string>("testament", newTestament.XmlNode.CreateNavigator().LocalName);
            Assert.AreEqual<string>("oldTestament", oldTestament.XmlNode.CreateNavigator().LocalName);

            model.Undo();
            Assert.AreEqual<string>("testament", oldTestament.XmlNode.CreateNavigator().LocalName);
            Assert.IsFalse(oldTestament.Modified);
            Assert.IsFalse(newTestament.Modified);

            model.Redo();
            Assert.AreEqual<string>("oldTestament", oldTestament.XmlNode.CreateNavigator().LocalName);
            Assert.IsTrue(oldTestament.Modified);
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RenameElementActionTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.AddAttribute(root, "test", "test");

            var att = ((XmlNode)root.XmlNode).Attributes["test"];
            model.RenameElement(BigXmlNodeInternal.Create(att, new int[] { 1 }, new int[] { 1 }), "test");
        }

        [TestMethod()]
        public void RenameElementActionTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.RenameElement(root, "root", "http://www.xmlstudio.com", "rb");

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(root.LocalName == "root");
            Assert.IsTrue(root.NamespaceURI == "http://www.xmlstudio.com");
            Assert.IsTrue(root.Prefix == "rb");
        }

        [TestMethod()]
        public void RenameElementActionTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.RenameElement(root, "root", "http://www.xmlstudio.com", "rb");

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(root.LocalName == "root");
            Assert.IsTrue(root.NamespaceURI == "http://www.xmlstudio.com");
            Assert.IsTrue(root.Prefix == "rb");

            model.Undo();

            Assert.IsFalse(root.Modified);
            Assert.IsTrue(root.LocalName == "root");
            Assert.IsTrue(root.NamespaceURI == string.Empty);
            Assert.IsTrue(root.Prefix == string.Empty);
        }

        [TestMethod()]
        public void RenameElementActionTest06() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.IsNotNull(root);

            model.ExpandNode(root, string.Empty);
            BigXmlNode oldTestament = root.ChildNodes[0];
            BigXmlNode newTestament = root.ChildNodes[1];

            model.RenameElement(oldTestament, "oldTestament");
            model.RenameElement(newTestament, "newTestament");

            Assert.IsTrue(oldTestament.Modified);
            Assert.IsTrue(newTestament.Modified);

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
                @"<bible>
  <oldTestament value=""Old Testament"" />
  <newTestament value=""New Testament"" />
</bible>", xml);

            model.Undo();
            model.Undo();

            Assert.IsFalse(oldTestament.Modified);
            Assert.IsFalse(newTestament.Modified);

            xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
                @"<bible>
  <testament value=""Old Testament"" />
  <testament value=""New Testament"" />
</bible>", xml);
        }

        [TestMethod()]
        public void RenameElementEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);
            var categories = root.ChildNodes[0];

            Action test = () => {
                model.RenameElement(categories, "newCategories");
            };

            var expectedSequence = new[] { "Modified", "NodeUpdated", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region SaveAs tests
        /// <summary>
        /// SaveAs() test.
        /// </summary>
        [TestMethod()]
        public void SaveAsTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root, string.Empty);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ExpandNode(oldTestament, string.Empty);
            model.ExpandNode(newTestament, string.Empty);

            model.RenameElement(oldTestament, "oldTestament");

            model.Save("test.xml", false);
        }
        #endregion

        #region AddAttribute tests
        /// <summary>
        /// Basic test of AddAttributeAction.
        /// </summary>
        [TestMethod()]
        public void AddAttributeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            Assert.IsFalse(model.Modified);
            model.AddAttribute(root, "att", "value");
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(((XmlNode)root.XmlNode).Attributes["att"] != null);
            Assert.AreEqual<string>("value", ((XmlNode)root.XmlNode).Attributes["att"].Value);
        }

        /// <summary>
        /// Test for XmlException when reading non wellformed xml document.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void AddAttributeTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest2);

            var root = model.GetRootElement();
            model.ExpandNode(root, string.Empty);
        }

        /// <summary>
        /// Test for XmlException when reading xml document without a root element.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void AddAttributeTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest3);

            var root = model.GetRootElement();
        }

        /// <summary>
        /// Testing adding an attribute with namespace to the BigXmlNode.
        /// </summary>
        [TestMethod()]
        public void AddAttributeTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.ExpandNode(root, string.Empty);

            var child1 = root.ChildNodes[0] as BigXmlNodeInternal;
            model.AddAttribute(child1, "t", "testAttribute", "http://www.xmlstudio.com", "testValue");

            Assert.IsTrue(child1.Modified);
            Assert.AreEqual<string>("testValue", child1.XmlNode.Attributes["testAttribute", "http://www.xmlstudio.com"].Value);
        }

        /// <summary>
        /// Test for XmlException when trying to add an attribute to the XmlNode which is not an element.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void AddAttributeTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.AddAttribute(root, "test", "test");

            Assert.IsTrue(root.Modified);

            XmlNode att = ((XmlNode)root.XmlNode).Attributes["test"];

            var node = BigXmlNodeInternal.Create(att, new int[] { 1 }, new int[] { 1 });
            model.AddAttribute(node, "test2", "test2");
        }

        /// <summary>
        /// Testing AddAttributeAction with Undo performed.
        /// </summary>
        [TestMethod()]
        public void AddAttributeTest06() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest4);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.ExpandNode(root, string.Empty);

            var child1 = root.ChildNodes[0] as BigXmlNodeInternal;
            model.AddAttribute(child1, "t", "testAttribute", "http://www.xmlstudio.com", "testValue");

            Assert.IsTrue(child1.Modified);

            Assert.AreEqual<string>("testValue", ((XmlNode)child1.XmlNode).Attributes["testAttribute", "http://www.xmlstudio.com"].Value);

            model.Undo();

            Assert.IsFalse(child1.Modified);
            Assert.AreEqual<int>(0, ((XmlNode)child1.XmlNode).Attributes.Count);
        }

        /// <summary>
        /// Testing AddAttributeAction with Undo performed.
        /// </summary>
        [TestMethod()]
        public void AddAttributeTest07() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.AddAttribute(root, "att", "value");

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(root.XmlNode.Attributes["att"] != null);
            Assert.AreEqual<string>("value", root.XmlNode.Attributes["att"].Value);

            model.Undo();

            Assert.IsFalse(root.Modified);
            Assert.AreEqual<int>(0, root.XmlNode.Attributes.Count);
        }

        [TestMethod()]
        public void AddAttributeEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            Action test = () => model.AddAttribute(root, "attribute", "value");

            var expectedSequence = new[] { "Modified", "AttributeAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod()]
        public void AddAttributeWithNamespaceEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            Action test = () => model.AddAttribute(root, "h", "attribute", "http://www.xmlstudio.cz/", "value");

            var expectedSequence = new[] { "Modified", "AttributeAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region RemoveAttribute tests
        /// <summary>
        /// Basic test for RemoveAttributeAction.
        /// </summary>
        [TestMethod()]
        public void RemoveAttributeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement();
            model.ExpandNode(root, string.Empty);

            var oldTestamentElement = root.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsFalse(model.Modified);
            model.RemoveAttribute(oldTestamentElement, "value");
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(oldTestamentElement.Modified);
            Assert.AreEqual<int>(0, ((XmlNode)oldTestamentElement.XmlNode).Attributes.Count);
        }

        /// <summary>
        /// RemoveAttribute with namespace test.
        /// </summary>
        [TestMethod()]
        public void RemoveAttributeTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest5);

            var root = model.GetRootElement();
            model.ExpandNode(root, string.Empty);

            var child2 = root.ChildNodes[1] as BigXmlNodeInternal;
            model.ExpandNode(child2, string.Empty);

            var subChild1 = child2.ChildNodes[0] as BigXmlNodeInternal;
            model.ExpandNode(subChild1, string.Empty);

            var subSubChild1 = subChild1.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsTrue(((XmlNode)subSubChild1.XmlNode).Attributes["style", "http://www.w3.org/HTML/1998/html4"].Value == "font-family: sans-serif;");
            model.RemoveAttribute(subSubChild1, "h", "style", "http://www.w3.org/HTML/1998/html4");

            Assert.IsTrue(subSubChild1.Modified);
            Assert.IsTrue(((XmlNode)subSubChild1.XmlNode).Attributes["style", "http://www.w3.org/HTML/1998/html4"] == null);
        }

        /// <summary>
        /// RemoveAttribute test with undo.
        /// </summary>
        [TestMethod()]
        public void RemoveAttributeTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.ExpandNode(root, string.Empty);

            var oldTestamentElement = root.ChildNodes[0] as BigXmlNodeInternal;

            model.RemoveAttribute(oldTestamentElement, "value");

            Assert.IsTrue(oldTestamentElement.Modified);
            Assert.AreEqual<int>(0, ((XmlNode)oldTestamentElement.XmlNode).Attributes.Count);

            model.Undo();

            Assert.IsFalse(oldTestamentElement.Modified);
            Assert.AreEqual<int>(1, ((XmlNode)oldTestamentElement.XmlNode).Attributes.Count);
        }

        /// <summary>
        /// RemoveAttribute test with undo.
        /// </summary>
        [TestMethod()]
        public void RemoveAttributeTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest5);

            var root = model.GetRootElement();
            model.ExpandNode(root, string.Empty);

            var child2 = root.ChildNodes[1];
            model.ExpandNode(child2, string.Empty);

            var subChild1 = child2.ChildNodes[0];
            model.ExpandNode(subChild1, string.Empty);

            var subSubChild1 = subChild1.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsTrue(subSubChild1.XmlNode.Attributes["style", "http://www.w3.org/HTML/1998/html4"].Value == "font-family: sans-serif;");
            model.RemoveAttribute(subSubChild1, "h", "style", "http://www.w3.org/HTML/1998/html4");

            Assert.IsTrue(subSubChild1.Modified);
            Assert.IsTrue(((XmlNode)subSubChild1.XmlNode).Attributes["style", "http://www.w3.org/HTML/1998/html4"] == null);

            model.Undo();

            Assert.IsFalse(subSubChild1.Modified);
            Assert.IsTrue(((XmlNode)subSubChild1.XmlNode).Attributes["style", "http://www.w3.org/HTML/1998/html4"].Value == "font-family: sans-serif;");
        }

        [TestMethod()]
        public void RemoveAttributeEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.AddAttribute(root, "attribute", "value");

            Action test = () => model.RemoveAttribute(root, "attribute");

            var expectedSequence = new[] { "Modified", "AttributeRemoved", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod()]
        public void RemoveAttributeWithNamespaceEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.AddAttribute(root, "h", "attribute", "http://www.xmlstudio.cz/", "value");

            Action test = () => {
                model.RemoveAttribute(root, "h", "attribute", "http://www.xmlstudio.cz/");
            };

            var expectedSequence = new[] { "Modified", "AttributeRemoved", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region GetRawXml tests
        /// <summary>
        /// Test for GetRawXml() method.
        /// </summary>
        [TestMethod()]
        public void GetRawXmlTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            string xml = model.GetRawXml();

            Assert.IsFalse(model.Modified);
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for GetRawXml() method.
        /// </summary>
        [TestMethod()]
        public void GetRawXmlTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ExpandNode(categories, string.Empty);
            model.ExpandNode(stock, string.Empty);

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories>
    <category />
    <category />
  </categories>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        /// <summary>
        /// Test for GetRawXml() method with undo.
        /// </summary>
        [TestMethod()]
        public void GetRawXmlTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ExpandNode(categories, string.Empty);
            model.ExpandNode(stock, string.Empty);

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories>
    <category />
    <category />
  </categories>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            //            xmlModel.Undo();

            //            xml = xmlModel.GetRawXml();
            //            Assert.AreEqual<string>(
            //@"<root>
            //  <categories>
            //    <category />
            //    <category />
            //  </categories>
            //  <stock>
            //  </stock>
            //</root>", xml);

            //            xmlModel.Undo();

            //            xml = xmlModel.GetRawXml();
            //            Assert.AreEqual<string>(
            //@"<root>
            //  <categories>
            //  </categories>
            //  <stock>
            //  </stock>
            //</root>", xml);

            //            xmlModel.Redo();

            //            xml = xmlModel.GetRawXml();
            //            Assert.AreEqual<string>(
            //@"<root>
            //  <categories>
            //    <category />
            //    <category />
            //  </categories>
            //  <stock>
            //  </stock>
            //</root>", xml);
        }

        /// <summary>
        /// Test for GetRawXml() method.
        /// </summary>
        [TestMethod()]
        public void GetRawXmlTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ExpandNode(oldTestament, string.Empty);
            model.ExpandNode(newTestament, string.Empty);

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));

            Assert.AreEqual<string>(
                @"<bible>
  <testament value=""Old Testament"">
    <book title=""Genesis"" />
    <book title=""Exodus"" />
    <book title=""Leviticus"" />
    <book title=""Numbers"" />
    <book title=""Deuteronomy"" />
    <book title=""Joshua"" />
    <book title=""Judges"" />
    <book title=""Ruth"" />
    <book title=""1 Samuel"" />
    <book title=""2 Samuel"" />
    <book title=""1 Kings"" />
    <book title=""2 Kings"" />
    <book title=""1 Chronicles"" />
    <book title=""2 Chronicles"" />
    <book title=""Ezra"" />
    <book title=""Nehemiah"" />
    <book title=""Esther"" />
    <book title=""Job"" />
    <book title=""Psalms"" />
    <book title=""Proverbs"" />
    <book title=""Ecclesiastes"" />
    <book title=""Song of Solomon"" />
    <book title=""Isaiah"" />
    <book title=""Jeremiah"" />
    <book title=""Lamentations"" />
    <book title=""Ezekiel"" />
    <book title=""Daniel"" />
    <book title=""Hosea"" />
    <book title=""Joel"" />
    <book title=""Amos"" />
    <book title=""Obadiah"" />
    <book title=""Jonah"" />
    <book title=""Micah"" />
    <book title=""Nahum"" />
    <book title=""Habakkuk"" />
    <book title=""Zephaniah"" />
    <book title=""Haggai"" />
    <book title=""Zechariah"" />
    <book title=""Malachi"" />
  </testament>
  <testament value=""New Testament"">
    <book title=""Matthew"" />
    <book title=""Mark"" />
    <book title=""Luke"" />
    <book title=""John"" />
    <book title=""Acts"" />
    <book title=""Romans"" />
    <book title=""1 Corinthians"" />
    <book title=""2 Corinthians"" />
    <book title=""Galatians"" />
    <book title=""Ephesians"" />
    <book title=""Philippians"" />
    <book title=""Colossians"" />
    <book title=""1 Thessalonians"" />
    <book title=""2 Thessalonians"" />
    <book title=""1 Timothy"" />
    <book title=""2 Timothy"" />
    <book title=""Titus"" />
    <book title=""Philemon"" />
    <book title=""Hebrews"" />
    <book title=""James"" />
    <book title=""1 Peter"" />
    <book title=""2 Peter"" />
    <book title=""1 John"" />
    <book title=""2 John"" />
    <book title=""3 John"" />
    <book title=""Jude"" />
    <book title=""Revelation"" />
  </testament>
</bible>", xml);
        }

        [TestMethod()]
        public void GetRawXmlEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ExpandNode(oldTestament, string.Empty);
            model.ExpandNode(newTestament, string.Empty);

            Action test = () => {
                model.GetRawXml();
            };

            var expectedSequence = new string[] { };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region AddChildNode tests
        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.First.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest01() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            Assert.IsFalse(model.Modified);
            Assert.AreEqual(37, model.TotalNodeCount);
            model.AddChildNode(root, node, InsertMode.First, null);
            Assert.AreEqual(38, model.TotalNodeCount);
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.After.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest02() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.After, categories);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(new[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new[] { 1, 2 }.SequenceEqual(node.Address));
            Assert.IsTrue(new[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.Before.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest03() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.Before, stock);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.Before.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest04() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.Before, categories);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.First with undo.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest05() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.First, null);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
            Assert.AreEqual(38, model.TotalNodeCount);
            model.Undo();
            Assert.AreEqual(37, model.TotalNodeCount);

            Assert.IsFalse(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(stock.Address));

            xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.After with undo.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest06() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.After, categories);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <stock />
</root>", xml);
            Assert.AreEqual(38, model.TotalNodeCount);
            model.Undo();
            Assert.AreEqual(37, model.TotalNodeCount);
            xml = model.GetRawXml();

            Assert.IsFalse(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <stock />
</root>", xml);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(stock.Address));
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.Before with undo.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest07() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.Before, categories);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
            Assert.AreEqual(38, model.TotalNodeCount);
            model.Undo();
            Assert.AreEqual(37, model.TotalNodeCount);
            Assert.IsFalse(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <stock />
</root>", xml);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(stock.Address));
        }

        /// <summary>
        /// Test for AddChildNodeAction. InsertMode.First with undo and redo.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest08() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var doc = model.XmlDocument;

            var element = doc.CreateElement("rb", "testElement", "http://www.xmlstudio.com");
            var node = BigXmlNodeInternal.Create(element);

            model.AddChildNode(root, node, InsertMode.First, null);

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(node.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(node.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 3 }.SequenceEqual(stock.Address));

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
            Assert.AreEqual(38, model.TotalNodeCount);
            model.Undo();
            Assert.AreEqual(37, model.TotalNodeCount);
            Assert.IsFalse(root.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(new int[] { 1, 1 }.SequenceEqual(categories.Address));
            Assert.IsTrue(new int[] { 1, 2 }.SequenceEqual(stock.Address));

            xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <categories />
  <stock />
</root>", xml);

            model.Redo();
            Assert.AreEqual(38, model.TotalNodeCount);
            Assert.IsTrue(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <rb:testElement xmlns:rb=""http://www.xmlstudio.com"" />
  <categories />
  <stock />
</root>", xml);
        }

        /// <summary>
        /// Test for Nodes property of the <see cref="IXmlModel"/>.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest09() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);

            var test = model.XmlDocument.CreateElement("test");

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var testNode = BigXmlNodeInternal.Create(test);
            model.AddChildNode(root, testNode, InsertMode.First, null);

            Assert.IsTrue(testNode.Address.SequenceEqual(new int[] { 1, 1 }));
            //Assert.IsTrue(xmlModel.Nodes.Contains(new KeyValuePair<int[], BigXmlNode>(testNode.Address, testNode)));
            Assert.AreEqual(38, model.TotalNodeCount);
            model.Undo();
            Assert.AreEqual(37, model.TotalNodeCount);
            //Assert.IsFalse(xmlModel.Nodes.Contains(new KeyValuePair<int[], BigXmlNode>(testNode.Address, testNode)));
        }

        /// <summary>
        /// Test for AddChildNode on programmatically created document.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest10() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;

            model.CreateRootElement("od", "order", "http://www.xmlstudio.cz");
            Assert.AreEqual(1, model.TotalNodeCount);

            var root = model.Root;

            Assert.IsTrue(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.IsNull(root.Parent);
            Assert.IsTrue(root.ExpandedRange.SequenceEqual(new int[] { }));
            Assert.AreEqual<int>(0, root.TotalChildCount);

            var doc = model.XmlDocument;
            var number = doc.CreateElement("od", "number", "http://www.xmlstudio.cz");
            var numberNode = BigXmlNodeInternal.Create(number);

            model.AddChildNode(root, numberNode, InsertMode.First, null);
            Assert.AreEqual(2, model.TotalNodeCount);

            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.IsTrue(numberNode.Parent == root);
            Assert.IsTrue(numberNode.Modified);
            Assert.IsTrue(numberNode.NodeState == ExpandState.Expanded);
            Assert.IsTrue(root.ExpandedRange.SequenceEqual(new int[] { 1 }));
            Assert.AreEqual<int>(1, root.TotalChildCount);

            var date = doc.CreateElement("od", "date", "http://www.xmlstudio.cz");
            var dateNode = BigXmlNodeInternal.Create(date);

            model.AddChildNode(root, dateNode, InsertMode.After, numberNode);

            Assert.AreEqual(3, model.TotalNodeCount);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.IsTrue(dateNode.Parent == root);
            Assert.IsTrue(dateNode.Modified);
            Assert.IsTrue(dateNode.NodeState == ExpandState.Expanded);
            Assert.IsTrue(root.ExpandedRange.SequenceEqual(new int[] { 1, 2 }));
            Assert.AreEqual<int>(2, root.TotalChildCount);

            var dateText = doc.CreateTextNode("today");
            var dateTextNode = BigXmlNodeInternal.Create(dateText);

            model.AddChildNode(dateNode, dateTextNode, InsertMode.First, null);

            Assert.AreEqual(4, model.TotalNodeCount);
            Assert.IsTrue(dateNode.NodeState == ExpandState.Expanded);
            Assert.IsTrue(dateNode.Parent == root);
            Assert.IsTrue(dateNode.Modified);
            Assert.IsTrue(dateNode.NodeState == ExpandState.Expanded);
            Assert.IsTrue(dateNode.ExpandedRange.SequenceEqual(new int[] { 1 }));
            Assert.AreEqual<int>(1, dateNode.TotalChildCount);
            Assert.AreEqual<int>(0, dateTextNode.TotalChildCount);

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<od:order xmlns:od=""http://www.xmlstudio.cz"">
  <od:number />
  <od:date>today</od:date>
</od:order>", xml);
        }

        [TestMethod()]
        public void AddChildNodeTest11() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            Assert.IsTrue(root.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, root.TotalChildCount);

            model.ExpandNode(root);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.IsTrue(root.ExpandedRange.SequenceEqual(new int[] { 1, 2 }));

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            Assert.IsFalse(model.Modified);
            model.RemoveNode(stock, true);
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(1, root.TotalChildCount);
        }

        [TestMethod()]
        public void AddChildNodeTest12() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            Assert.IsTrue(root.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(2, root.TotalChildCount);

            model.ExpandNode(root, "2");
            Assert.IsTrue(root.NodeState == ExpandState.PartiallyExpanded);
            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.IsTrue(root.ExpandedRange.SequenceEqual(new int[] { 2 }));

            var stock = root.ChildNodes[1];

            model.RemoveNode(stock, true);

            Assert.IsTrue(root.NodeState == ExpandState.Collapsed);
            Assert.AreEqual<int>(1, root.TotalChildCount);
        }

        /// <summary>
        /// Test for appending the child param.
        /// </summary>
        [TestMethod()]
        public void AddChildNodeTest13() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var newChild = model.CreateElement("LastChild");
            model.AddChildNode(root, newChild, InsertMode.Last, null);

            // Assert.IsTrue(xmlModel.Nodes[newChild.Address] == newChild);
            Assert.AreEqual<int>(3, root.ChildNodes.Count);

            model.Undo();

            // Assert.IsFalse(xmlModel.Nodes.ContainsKey(newChild.Address));
            Assert.AreEqual<int>(2, root.ChildNodes.Count);
        }

        [TestMethod()]
        public void AddChildNodeEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);
            var newChild = model.CreateElement("newChild");

            Action test = () => {
                model.AddChildNode(root, newChild, InsertMode.Last, null);
            };

            var expectedSequence = new[] { "Modified", "NodeAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod]
        public void AddChildNodeTest14() {
            var model = ModelFactory.CreateXmlModel();
            Assert.IsNull(model.GetRootElement());
            var element = model.CreateElement("root");
            model.AddChildNode(null, element, InsertMode.First, null);
            Assert.IsNotNull(model.GetRootElement());
        }
        #endregion

        #region CreateRootElement tests
        /// <summary>
        /// CreateRootElement test.
        /// </summary>
        [TestMethod()]
        public void CreateRootElementTest01() {
            var model = ModelFactory.CreateXmlModel();

            model.CreateRootElement("testRoot");

            var root = model.GetRootElement();

            Assert.IsNotNull(root);
            Assert.IsTrue(root.Modified);

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(@"<testRoot />", xml);
        }

        /// <summary>
        /// CreateRootElement test.
        /// </summary>
        [TestMethod()]
        public void CreateRootElementTest02() {
            var model = ModelFactory.CreateXmlModel();

            model.CreateRootElement("rb", "testRoot", "http://www.xmlstudio.com");

            var root = model.GetRootElement();

            Assert.IsNotNull(root);
            Assert.IsTrue(root.Modified);

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(@"<rb:testRoot xmlns:rb=""http://www.xmlstudio.com"" />", xml);
        }

        /// <summary>
        /// CreateRootElement test.
        /// </summary>
        [TestMethod()]
        public void CreateRootElementTest03() {
            var model = ModelFactory.CreateXmlModel();

            model.CreateRootElement("testRoot");

            var root = model.GetRootElement();

            Assert.IsNotNull(root);
            Assert.IsTrue(root.Modified);

            Assert.IsNotNull(model.GetRootElement());
            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(@"<testRoot />", xml);

            model.Undo();
            Assert.IsNull(model.GetRootElement());
        }

        /// <summary>
        /// Test for CreateRootElement.
        /// </summary>
        [TestMethod()]
        public void CreateRootElementTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.CreateRootElement("rootElement");

            var root = model.GetRootElement();

            Assert.IsNotNull(root);
            Assert.AreEqual<string>("rootElement", root.Name);
            Assert.IsTrue(root.Modified);
            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
        }

        [TestMethod()]
        public void CreateRootElementEventsTest() {
            var model = ModelFactory.CreateXmlModel();

            Action test = () => model.CreateRootElement("root");

            var expectedSequence = new[] { "Root", "Modified", "RootElementAdded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region EmptyDocument tests
        /// <summary>
        /// Test to create xml document from scratch.
        /// </summary>
        [TestMethod()]
        public void CreateEmptyDocumentTest01() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.CreateRootElement("root");
            Assert.IsTrue(model.Modified);

            var root = model.GetRootElement();

            var doc = model.XmlDocument;
            var child1 = doc.CreateElement("child1");
            var child1Node = BigXmlNodeInternal.Create(child1);
            model.AddChildNode(root, child1Node, InsertMode.First, null);

            var child2 = doc.CreateElement("child2");
            var child2Node = BigXmlNodeInternal.Create(child2);
            model.AddChildNode(root, child2Node, InsertMode.After, child1Node);

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <child1 />
  <child2 />
</root>", xml);

            model.AddAttribute(child1Node, "attribute", "value");

            xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <child1 attribute=""value"" />
  <child2 />
</root>", xml);
        }
        #endregion

        #region RemoveNode tests
        /// <summary>
        /// Test for RemoveNodeAction.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var child1 = root.ChildNodes[0];
            var child2 = root.ChildNodes[1];

            model.ExpandNode(child1, string.Empty);
            model.ExpandNode(child2, string.Empty);

            Assert.IsFalse(model.Modified);
            Assert.AreEqual<int>(7, model.NodeCount);

            model.RemoveNode(child1, true);

            Assert.IsTrue(model.Modified);
            Assert.AreEqual<int>(4, model.NodeCount);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(child2.Modified);

            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.IsTrue(child2.Address.SequenceEqual(new int[] { 1, 1 }));

            model.Undo();

            Assert.AreEqual<int>(7, model.NodeCount);
            xml = model.GetRawXml();

            Assert.AreEqual<string>(@"<root>
  <categories>
    <category />
    <category />
  </categories>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        /// <summary>
        /// Test for RemoveNodeAction.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ExpandNode(categories);
            model.ExpandNode(stock);

            var category1 = categories.ChildNodes[0];
            model.ExpandNode(category1);

            Assert.IsTrue(categories.NodeState == ExpandState.Expanded);

            Assert.AreEqual<int>(12, model.NodeCount);
            model.RemoveNode(categories, false);
            Assert.AreEqual<int>(11, model.NodeCount);

            Assert.IsTrue(root.Modified);
            string xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<string>(
@"<root>
  <category>
    <item />
    <item />
    <item />
    <item />
    <item />
  </category>
  <category />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 3 }));

            Assert.IsTrue(stock.ChildNodes[0].Address.SequenceEqual(new int[] { 1, 3, 1 }));
            Assert.IsTrue(root.ChildNodes[0].Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(root.ChildNodes[1].Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(root.ChildNodes[2].Address.SequenceEqual(new int[] { 1, 3 }));

            Assert.IsTrue(root.ChildNodes[0].Modified);
            Assert.IsTrue(root.ChildNodes[1].Modified);
            Assert.IsFalse(root.ChildNodes[2].Modified);

            model.Undo();

            Assert.AreEqual<int>(12, model.NodeCount);

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories>
    <category>
      <item />
      <item />
      <item />
      <item />
      <item />
    </category>
    <category />
  </categories>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        /// <summary>
        /// Test for RemoveNodeAction.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest03() {
            string xml =
@"<root>
	<child1>
		<subChild1 />
		<subChild2 />
		<subChild3 />
	</child1>
	<child2>
		<subChild1>
		</subChild1>
		<subChild2>
			<subSubChild1>
				<subSubSubChild1 />
				<subSubSubChild2 />
				<subSubSubChild3 />
			</subSubChild1>
			<subSubChild2>
				<subSubSubChild1 />
			</subSubChild2>
			<subSubChild3>
				<subSubSubChild1 />
				<subSubSubChild2 />
			</subSubChild3>
		</subChild2>
		<subChild3 />
		<subChild4 />
	</child2>
	<child3>
		<subChild1 />
	</child3>
</root>";

            var root = TreeBuilder.BuildTree(xml);

            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Root = root;

            Assert.IsNotNull(root);
            TreeBuilder.AdjustAddresses(root, model);

            model.RemoveNode(root.ChildNodes[1].ChildNodes[1], false);
            Assert.IsTrue(root.ChildNodes[1].Modified);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subSubChild1>
      <subSubSubChild1 />
      <subSubSubChild2 />
      <subSubSubChild3 />
    </subSubChild1>
    <subSubChild2>
      <subSubSubChild1 />
    </subSubChild2>
    <subSubChild3>
      <subSubSubChild1 />
      <subSubSubChild2 />
    </subSubChild3>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);
        }

        /// <summary>
        /// Test for RemoveNodeAction with undo.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest04() {
            string xml =
@"<root>
	<child1>
		<subChild1 />
		<subChild2 />
		<subChild3 />
	</child1>
	<child2>
		<subChild1>
		</subChild1>
		<subChild2>
			<subSubChild1>
				<subSubSubChild1 />
				<subSubSubChild2 />
				<subSubSubChild3 />
			</subSubChild1>
			<subSubChild2>
				<subSubSubChild1 />
			</subSubChild2>
			<subSubChild3>
				<subSubSubChild1 />
				<subSubSubChild2 />
			</subSubChild3>
		</subChild2>
		<subChild3 />
		<subChild4 />
	</child2>
	<child3>
		<subChild1 />
	</child3>
</root>";

            var root = TreeBuilder.BuildTree(xml);

            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Root = root;

            Assert.IsNotNull(root);
            TreeBuilder.AdjustAddresses(root, model);

            model.RemoveNode(root.ChildNodes[1].ChildNodes[1], false);
            Assert.IsTrue(root.ChildNodes[1].Modified);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subSubChild1>
      <subSubSubChild1 />
      <subSubSubChild2 />
      <subSubSubChild3 />
    </subSubChild1>
    <subSubChild2>
      <subSubSubChild1 />
    </subSubChild2>
    <subSubChild3>
      <subSubSubChild1 />
      <subSubSubChild2 />
    </subSubChild3>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Undo();

            Assert.IsFalse(root.ChildNodes[1].Modified);
            rawXml = model.GetRawXml();

            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild2>
      <subSubChild1>
        <subSubSubChild1 />
        <subSubSubChild2 />
        <subSubSubChild3 />
      </subSubChild1>
      <subSubChild2>
        <subSubSubChild1 />
      </subSubChild2>
      <subSubChild3>
        <subSubSubChild1 />
        <subSubSubChild2 />
      </subSubChild3>
    </subChild2>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);
        }

        /// <summary>
        /// Test for RemoveNodeAction with undo.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest05() {
            string xml =
@"<root>
	<child1>
		<subChild1 />
		<subChild2 />
		<subChild3 />
	</child1>
	<child2>
		<subChild1>
		</subChild1>
		<subChild2>
			<subSubChild1>
				<subSubSubChild1 />
				<subSubSubChild2 />
				<subSubSubChild3 />
			</subSubChild1>
			<subSubChild2>
				<subSubSubChild1 />
			</subSubChild2>
			<subSubChild3>
				<subSubSubChild1 />
				<subSubSubChild2 />
			</subSubChild3>
		</subChild2>
		<subChild3 />
		<subChild4 />
	</child2>
	<child3>
		<subChild1 />
	</child3>
</root>";

            var root = TreeBuilder.BuildTree(xml);

            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Root = root;

            Assert.IsNotNull(root);
            TreeBuilder.AdjustAddresses(root, model);

            model.RemoveNode(root.ChildNodes[1].ChildNodes[1], true);
            Assert.IsTrue(root.ChildNodes[1].Modified);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Undo();

            Assert.IsFalse(root.ChildNodes[1].Modified);

            rawXml = model.GetRawXml();

            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild2>
      <subSubChild1>
        <subSubSubChild1 />
        <subSubSubChild2 />
        <subSubSubChild3 />
      </subSubChild1>
      <subSubChild2>
        <subSubSubChild1 />
      </subSubChild2>
      <subSubChild3>
        <subSubSubChild1 />
        <subSubSubChild2 />
      </subSubChild3>
    </subChild2>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);
        }

        /// <summary>
        /// Test for RemoveNodeAction with undo.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest06() {
            string xml =
@"<root>
	<child1>
		<subChild1 />
		<subChild2 />
		<subChild3 />
	</child1>
	<child2>
		<subChild1>
		</subChild1>
		<subChild2>
			<subSubChild1>
				<subSubSubChild1 />
				<subSubSubChild2 />
				<subSubSubChild3 />
			</subSubChild1>
			<subSubChild2>
				<subSubSubChild1 />
			</subSubChild2>
			<subSubChild3>
				<subSubSubChild1 />
				<subSubSubChild2 />
			</subSubChild3>
		</subChild2>
		<subChild3 />
		<subChild4 />
	</child2>
	<child3>
		<subChild1 />
	</child3>
</root>";

            var root = TreeBuilder.BuildTree(xml);

            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Root = root;

            Assert.IsNotNull(root);
            TreeBuilder.AdjustAddresses(root, model);

            model.RemoveNode(root.ChildNodes[1].ChildNodes[1], false);
            Assert.IsTrue(root.ChildNodes[1].Modified);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subSubChild1>
      <subSubSubChild1 />
      <subSubSubChild2 />
      <subSubSubChild3 />
    </subSubChild1>
    <subSubChild2>
      <subSubSubChild1 />
    </subSubChild2>
    <subSubChild3>
      <subSubSubChild1 />
      <subSubSubChild2 />
    </subSubChild3>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Undo();

            Assert.IsFalse(root.ChildNodes[1].Modified);

            rawXml = model.GetRawXml();

            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild2>
      <subSubChild1>
        <subSubSubChild1 />
        <subSubSubChild2 />
        <subSubSubChild3 />
      </subSubChild1>
      <subSubChild2>
        <subSubSubChild1 />
      </subSubChild2>
      <subSubChild3>
        <subSubSubChild1 />
        <subSubSubChild2 />
      </subSubChild3>
    </subChild2>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Redo();

            Assert.IsTrue(root.ChildNodes[1].Modified);

            rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subSubChild1>
      <subSubSubChild1 />
      <subSubSubChild2 />
      <subSubSubChild3 />
    </subSubChild1>
    <subSubChild2>
      <subSubSubChild1 />
    </subSubChild2>
    <subSubChild3>
      <subSubSubChild1 />
      <subSubSubChild2 />
    </subSubChild3>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);
        }

        /// <summary>
        /// Test for RemoveNodeAction with undo and redo.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest07() {
            string xml =
@"<root>
	<child1>
		<subChild1 />
		<subChild2 />
		<subChild3 />
	</child1>
	<child2>
		<subChild1>
		</subChild1>
		<subChild2>
			<subSubChild1>
				<subSubSubChild1 />
				<subSubSubChild2 />
				<subSubSubChild3 />
			</subSubChild1>
			<subSubChild2>
				<subSubSubChild1 />
			</subSubChild2>
			<subSubChild3>
				<subSubSubChild1 />
				<subSubSubChild2 />
			</subSubChild3>
		</subChild2>
		<subChild3 />
		<subChild4 />
	</child2>
	<child3>
		<subChild1 />
	</child3>
</root>";

            var root = TreeBuilder.BuildTree(xml);

            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Root = root;

            Assert.IsNotNull(root);
            TreeBuilder.AdjustAddresses(root, model);

            model.RemoveNode(root.ChildNodes[1].ChildNodes[1], true);

            Assert.IsTrue(root.ChildNodes[1].Modified);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Undo();

            Assert.IsFalse(root.ChildNodes[1].Modified);

            rawXml = model.GetRawXml();

            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild2>
      <subSubChild1>
        <subSubSubChild1 />
        <subSubSubChild2 />
        <subSubSubChild3 />
      </subSubChild1>
      <subSubChild2>
        <subSubSubChild1 />
      </subSubChild2>
      <subSubChild3>
        <subSubSubChild1 />
        <subSubSubChild2 />
      </subSubChild3>
    </subChild2>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);

            model.Redo();

            Assert.IsTrue(root.ChildNodes[1].Modified);

            rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(
@"<root>
  <child1>
    <subChild1 />
    <subChild2 />
    <subChild3 />
  </child1>
  <child2>
    <subChild1>
    </subChild1>
    <subChild3 />
    <subChild4 />
  </child2>
  <child3>
    <subChild1 />
  </child3>
</root>", rawXml);
        }

        [TestMethod()]
        public void RemoveNodeTest08() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.RemoveNode(categories, true);

            Assert.IsNotNull(root.ChildNodes[0]);
            Assert.AreEqual(stock, root.ChildNodes[0]);
            Assert.AreEqual<int>(1, root.TotalChildCount);

            model.Undo();

            Assert.IsNotNull(root.ChildNodes[0]);
            Assert.IsNotNull(root.ChildNodes[1]);

            Assert.AreEqual(categories, root.ChildNodes[0]);
            Assert.AreEqual(stock, root.ChildNodes[1]);
        }

        /// <summary>
        /// Test for RemoveNodeAction. Tests its undo functionality.
        /// </summary>
        [TestMethod()]
        public void RemoveNodeTest10() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest6);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var child1 = root.ChildNodes[0];
            model.ExpandNode(child1);

            Assert.AreEqual<int>(5, root.ChildNodes.Count);
            Assert.AreEqual<int>(5, root.TotalChildCount);

            model.RemoveNode(child1, false);

            Assert.AreEqual<int>(6, root.ChildNodes.Count);
            Assert.AreEqual<int>(6, root.TotalChildCount);

            string xml = model.GetRawXml();

            model.Undo();

            xml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.AreEqual<int>(5, root.ChildNodes.Count);
            Assert.AreEqual<int>(5, root.TotalChildCount);
        }

        /// <summary>
        /// Test for RemoveNode testing that param cannot be removed without its subtree when it is not fully expanded.
        /// </summary>
        [ExpectedException(typeof(InvalidOperationException))]
        [TestMethod()]
        public void RemoveNodeTest09() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.RemoveNode(stock, false);
        }

        [TestMethod()]
        public void RemoveNodeEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);
            var categories = root.ChildNodes[0];

            Action test = () => {
                model.RemoveNode(categories, true);
            };

            var expectedSequence = new[] { "Modified", "NodeRemoved", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod]
        public void RemoveNodeTest11() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            model.RemoveNode(root, true);

            Assert.IsNull(model.GetRootElement());

            model.Undo();

            Assert.IsNotNull(model.GetRootElement());
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RemoveNodeTest12() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.ExpandAll();

            var root = model.GetRootElement();
            model.RemoveNode(root, false);
        }

        [TestMethod]
        public void RemoveNodeTest13() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.ExpandAll();

            var root = model.GetRootElement();
            var child2 = root.ChildNodes[1];
            model.RemoveNode(child2, true);

            model.RemoveNode(root, false);

            model.Undo();

            Assert.AreEqual(root, model.GetRootElement());
        }
        #endregion

        #region Extension methods tests
        [TestMethod()]
        public void InsertAferTest01() {
            var first = BigXmlNodeInternal.Create(new int[] { 1 });
            var second = BigXmlNodeInternal.Create(new int[] { 2 });
            var third = BigXmlNodeInternal.Create(new int[] { 3 });
            List<BigXmlNode> nodes = new List<BigXmlNode>() { first, second, third };

            var toInsert = BigXmlNodeInternal.Create(new int[] { 99 });
            nodes.InsertAfter(toInsert, second);

            Assert.IsNotNull(nodes);
            Assert.IsTrue(nodes[2] == toInsert);
        }

        [TestMethod()]
        public void InsertAferTest02() {
            var first = BigXmlNodeInternal.Create(new int[] { 1 });
            var second = BigXmlNodeInternal.Create(new int[] { 2 });
            var third = BigXmlNodeInternal.Create(new int[] { 3 });
            List<BigXmlNode> nodes = new List<BigXmlNode>() { first, second, third };

            var toInsert = BigXmlNodeInternal.Create(new int[] { 99 });
            nodes.InsertAfter(toInsert, third);

            Assert.IsNotNull(nodes);
            Assert.IsTrue(nodes[3] == toInsert);
        }

        [TestMethod()]
        public void InsertAferTest03() {
            var first = BigXmlNodeInternal.Create(new int[] { 1 });
            var second = BigXmlNodeInternal.Create(new int[] { 2 });
            var third = BigXmlNodeInternal.Create(new int[] { 3 });
            List<BigXmlNode> nodes = new List<BigXmlNode>() { first, second, third };

            var toInsert = BigXmlNodeInternal.Create(new int[] { 99 });
            nodes.InsertAfter(toInsert, first);

            Assert.IsNotNull(nodes);
            Assert.IsTrue(nodes[1] == toInsert);
        }
        #endregion

        #region ChangeNodeOrderAction tests
        /// <summary>
        /// Test for ChangeNodeOrderAction.
        /// </summary>
        [TestMethod()]
        public void ChangeNodeOrderActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            Assert.IsFalse(model.Modified);
            model.ChangeNodeOrder(stock, null);
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(root.ChildNodes[0] == stock);
            Assert.IsTrue(root.ChildNodes[1] == categories);

            Assert.IsTrue(((BigXmlNodeInternal)root).XmlNode.FirstChild == ((BigXmlNodeInternal)stock).XmlNode);
            Assert.IsTrue(((BigXmlNodeInternal)root).XmlNode.ChildNodes[1] == ((BigXmlNodeInternal)categories).XmlNode);

            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 1 }));

            Assert.IsTrue(stock.Parent == root);
            Assert.IsTrue(categories.Parent == root);

            Assert.IsTrue(root.ChildNodes.Count == 2);
        }

        /// <summary>
        /// Test for ChangeNodeOrderAction.
        /// </summary>
        [TestMethod()]
        public void ChangeNodeOrderActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathShiporder);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root, string.Empty);
            var orderPerson = root.ChildNodes[0] as BigXmlNodeInternal;
            var shipTo = root.ChildNodes[1] as BigXmlNodeInternal;
            var item1 = root.ChildNodes[2] as BigXmlNodeInternal;
            var item2 = root.ChildNodes[3] as BigXmlNodeInternal;
            var lest = root.ChildNodes[4] as BigXmlNodeInternal;

            model.ChangeNodeOrder(orderPerson, lest);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(orderPerson.Modified);
            Assert.IsFalse(shipTo.Modified);
            Assert.IsFalse(item1.Modified);
            Assert.IsFalse(item2.Modified);
            Assert.IsFalse(lest.Modified);

            Assert.IsTrue(root.ChildNodes[0] == shipTo);
            Assert.IsTrue(root.ChildNodes[1] == item1);
            Assert.IsTrue(root.ChildNodes[2] == item2);
            Assert.IsTrue(root.ChildNodes[3] == lest);
            Assert.IsTrue(root.ChildNodes[4] == orderPerson);

            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[0] == shipTo.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == item1.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[2] == item2.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[3] == lest.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[4] == orderPerson.XmlNode);

            Assert.IsTrue(shipTo.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(item1.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(item2.Address.SequenceEqual(new int[] { 1, 3 }));
            Assert.IsTrue(lest.Address.SequenceEqual(new int[] { 1, 4 }));
            Assert.IsTrue(orderPerson.Address.SequenceEqual(new int[] { 1, 5 }));

            Assert.IsTrue(shipTo.Parent == root);
            Assert.IsTrue(item1.Parent == root);
            Assert.IsTrue(item2.Parent == root);
            Assert.IsTrue(lest.Parent == root);
            Assert.IsTrue(orderPerson.Parent == root);
        }

        /// <summary>
        /// Test for ChangeNodeOrderAction.
        /// </summary>
        [TestMethod()]
        public void ChangeNodeOrderActionTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathShiporder);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root, string.Empty);
            var orderPerson = root.ChildNodes[0] as BigXmlNodeInternal;
            var shipTo = root.ChildNodes[1] as BigXmlNodeInternal;
            var item1 = root.ChildNodes[2] as BigXmlNodeInternal;
            var item2 = root.ChildNodes[3] as BigXmlNodeInternal;
            var lest = root.ChildNodes[4] as BigXmlNodeInternal;

            model.ChangeNodeOrder(lest, orderPerson);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(orderPerson.Modified);
            Assert.IsFalse(shipTo.Modified);
            Assert.IsFalse(item1.Modified);
            Assert.IsFalse(item2.Modified);
            Assert.IsFalse(lest.Modified);

            Assert.IsTrue(root.ChildNodes[0] == orderPerson);
            Assert.IsTrue(root.ChildNodes[1] == lest);
            Assert.IsTrue(root.ChildNodes[2] == shipTo);
            Assert.IsTrue(root.ChildNodes[3] == item1);
            Assert.IsTrue(root.ChildNodes[4] == item2);

            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[0] == orderPerson.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == lest.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[2] == shipTo.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[3] == item1.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[4] == item2.XmlNode);

            Assert.IsTrue(orderPerson.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(lest.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(shipTo.Address.SequenceEqual(new int[] { 1, 3 }));
            Assert.IsTrue(item1.Address.SequenceEqual(new int[] { 1, 4 }));
            Assert.IsTrue(item2.Address.SequenceEqual(new int[] { 1, 5 }));

            Assert.IsTrue(shipTo.Parent == root);
            Assert.IsTrue(item1.Parent == root);
            Assert.IsTrue(item2.Parent == root);
            Assert.IsTrue(lest.Parent == root);
            Assert.IsTrue(orderPerson.Parent == root);
        }

        /// <summary>
        /// Test for ChangeNodeOrderAction with undo.
        /// </summary>
        [TestMethod()]
        public void ChangeNodeOrderActionTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            model.ChangeNodeOrder(stock, null);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(root.ChildNodes[0] == stock);
            Assert.IsTrue(root.ChildNodes[1] == categories);

            Assert.IsTrue(((XmlNode)root.XmlNode).FirstChild == stock.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == categories.XmlNode);

            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 1 }));

            Assert.IsTrue(stock.Parent == root);
            Assert.IsTrue(categories.Parent == root);

            Assert.IsTrue(root.ChildNodes.Count == 2);

            model.Undo();

            Assert.IsFalse(root.Modified);
            Assert.IsFalse(stock.Modified);
            Assert.IsFalse(categories.Modified);

            Assert.IsTrue(root.ChildNodes[0] == categories);
            Assert.IsTrue(root.ChildNodes[1] == stock);

            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 2 }));

            Assert.IsTrue(stock.Parent == root);
            Assert.IsTrue(categories.Parent == root);

            Assert.IsTrue(root.ChildNodes.Count == 2);

            model.Redo();

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            Assert.IsTrue(root.ChildNodes[0] == stock);
            Assert.IsTrue(root.ChildNodes[1] == categories);

            Assert.IsTrue(((XmlNode)root.XmlNode).FirstChild == stock.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == categories.XmlNode);

            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 1 }));

            Assert.IsTrue(stock.Parent == root);
            Assert.IsTrue(categories.Parent == root);

            Assert.IsTrue(root.ChildNodes.Count == 2);
        }

        /// <summary>
        /// Test for ChangeNodeOrderAction with undo.
        /// </summary>
        [TestMethod()]
        public void ChangeNodeOrderActionTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathShiporder);

            var root = model.GetRootElement() as BigXmlNodeInternal;

            model.ExpandNode(root, string.Empty);
            var orderPerson = root.ChildNodes[0] as BigXmlNodeInternal;
            var shipTo = root.ChildNodes[1] as BigXmlNodeInternal;
            var item1 = root.ChildNodes[2] as BigXmlNodeInternal;
            var item2 = root.ChildNodes[3] as BigXmlNodeInternal;
            var lest = root.ChildNodes[4] as BigXmlNodeInternal;

            model.ChangeNodeOrder(orderPerson, lest);

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(orderPerson.Modified);
            Assert.IsFalse(shipTo.Modified);
            Assert.IsFalse(item1.Modified);
            Assert.IsFalse(item2.Modified);
            Assert.IsFalse(lest.Modified);

            Assert.IsTrue(root.ChildNodes[0] == shipTo);
            Assert.IsTrue(root.ChildNodes[1] == item1);
            Assert.IsTrue(root.ChildNodes[2] == item2);
            Assert.IsTrue(root.ChildNodes[3] == lest);
            Assert.IsTrue(root.ChildNodes[4] == orderPerson);

            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[0] == shipTo.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == item1.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[2] == item2.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[3] == lest.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[4] == orderPerson.XmlNode);

            Assert.IsTrue(shipTo.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(item1.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(item2.Address.SequenceEqual(new int[] { 1, 3 }));
            Assert.IsTrue(lest.Address.SequenceEqual(new int[] { 1, 4 }));
            Assert.IsTrue(orderPerson.Address.SequenceEqual(new int[] { 1, 5 }));

            Assert.IsTrue(shipTo.Parent == root);
            Assert.IsTrue(item1.Parent == root);
            Assert.IsTrue(item2.Parent == root);
            Assert.IsTrue(lest.Parent == root);
            Assert.IsTrue(orderPerson.Parent == root);

            model.Undo();

            Assert.IsFalse(root.Modified);
            Assert.IsFalse(orderPerson.Modified);
            Assert.IsFalse(shipTo.Modified);
            Assert.IsFalse(item1.Modified);
            Assert.IsFalse(item2.Modified);
            Assert.IsFalse(lest.Modified);

            Assert.IsTrue(root.ChildNodes[0] == orderPerson);
            Assert.IsTrue(root.ChildNodes[1] == shipTo);
            Assert.IsTrue(root.ChildNodes[2] == item1);
            Assert.IsTrue(root.ChildNodes[3] == item2);
            Assert.IsTrue(root.ChildNodes[4] == lest);

            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[0] == orderPerson.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == shipTo.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[2] == item1.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[3] == item2.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[4] == lest.XmlNode);

            Assert.IsTrue(orderPerson.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(shipTo.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(item1.Address.SequenceEqual(new int[] { 1, 3 }));
            Assert.IsTrue(item2.Address.SequenceEqual(new int[] { 1, 4 }));
            Assert.IsTrue(lest.Address.SequenceEqual(new int[] { 1, 5 }));

            Assert.IsTrue(orderPerson.Parent == root);
            Assert.IsTrue(shipTo.Parent == root);
            Assert.IsTrue(item1.Parent == root);
            Assert.IsTrue(item2.Parent == root);
            Assert.IsTrue(lest.Parent == root);

            model.Redo();

            Assert.IsTrue(root.Modified);
            Assert.IsFalse(orderPerson.Modified);
            Assert.IsFalse(shipTo.Modified);
            Assert.IsFalse(item1.Modified);
            Assert.IsFalse(item2.Modified);
            Assert.IsFalse(lest.Modified);

            Assert.IsTrue(root.ChildNodes[0] == shipTo);
            Assert.IsTrue(root.ChildNodes[1] == item1);
            Assert.IsTrue(root.ChildNodes[2] == item2);
            Assert.IsTrue(root.ChildNodes[3] == lest);
            Assert.IsTrue(root.ChildNodes[4] == orderPerson);

            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[0] == shipTo.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[1] == item1.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[2] == item2.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[3] == lest.XmlNode);
            Assert.IsTrue(((XmlNode)root.XmlNode).ChildNodes[4] == orderPerson.XmlNode);

            Assert.IsTrue(shipTo.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(item1.Address.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(item2.Address.SequenceEqual(new int[] { 1, 3 }));
            Assert.IsTrue(lest.Address.SequenceEqual(new int[] { 1, 4 }));
            Assert.IsTrue(orderPerson.Address.SequenceEqual(new int[] { 1, 5 }));

            Assert.IsTrue(shipTo.Parent == root);
            Assert.IsTrue(item1.Parent == root);
            Assert.IsTrue(item2.Parent == root);
            Assert.IsTrue(lest.Parent == root);
            Assert.IsTrue(orderPerson.Parent == root);
        }

        [TestMethod]
        public void ChangeNodeOrderActionTest06() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement();

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ChangeNodeOrder(newTestament, null);

            Assert.AreEqual(newTestament, root.ChildNodes[0]);
            Assert.AreEqual(oldTestament, root.ChildNodes[1]);

            model.ExpandNode(newTestament);

            var matthew = newTestament.ChildNodes[0];
            IBigXmlAttribute matthewTitle;
            matthew.Attributes.TryGetValue(":title:", out matthewTitle);
            Assert.IsNotNull(matthewTitle);
            Assert.AreEqual<string>("Matthew", matthewTitle.Value);

            var mark = newTestament.ChildNodes[1];
            IBigXmlAttribute markTitle;
            mark.Attributes.TryGetValue(":title:", out markTitle);
            Assert.IsNotNull(markTitle);
            Assert.AreEqual<string>("Mark", markTitle.Value);
        }

        [TestMethod]
        public void ChangeNodeOrderActionTest07() {
            string newPath = "ChangeNodeOrderActionTest07Output.xml";
            File.Copy(Common.PathBible1, newPath);
            var model = ModelFactory.CreateXmlModel();
            model.Open(newPath);
            var root = model.GetRootElement();

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ChangeNodeOrder(newTestament, null);
            model.ExpandNode(oldTestament);
            model.ExpandNode(newTestament);

            model.Save(false);
            bool areEqual = newPath.FileCompare("ChangeNodeOrderActionTest07OutputCorrect.xml");
            Assert.IsTrue(areEqual);
        }

        [TestMethod]
        public void ChangeNodeOrderActionTest08() {
            string newPath = "ChangeNodeOrderActionTest08Output.xml";
            File.Copy(Common.PathBible1, newPath);
            var model = ModelFactory.CreateXmlModel();
            model.Open(newPath);
            var root = model.GetRootElement();

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ChangeNodeOrder(newTestament, null);
            model.ExpandNode(oldTestament);
            model.ExpandNode(newTestament, "1-10");

            model.Save(false);
            bool areEqual = newPath.FileCompare("ChangeNodeOrderActionTest07OutputCorrect.xml");
            Assert.IsTrue(areEqual);
        }

        [TestMethod]
        public void ChangeNodeOrderActionTest09() {
            string newPath = "ChangeNodeOrderActionTest09Output.xml";
            File.Copy(Common.PathBible1, newPath);
            var model = ModelFactory.CreateXmlModel();
            model.Open(newPath);
            var root = model.GetRootElement();

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            model.ChangeNodeOrder(newTestament, null);
            model.ExpandNode(oldTestament);
            model.ExpandNode(newTestament, "1-10,12-15");

            model.Save(false);
            bool areEqual = newPath.FileCompare("ChangeNodeOrderActionTest07OutputCorrect.xml");
            Assert.IsTrue(areEqual);
        }

        [TestMethod()]
        public void ChangeNodeOrderActionEventsTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            Action test = () => model.ChangeNodeOrder(stock, null);

            var expectedSequence = new[] { "Modified", "SubtreeUpdated", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);

            test = () => {
                model.Undo();
            };

            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region Expand text nodes tests
        [TestMethod()]
        public void ExpandTextNodeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ExpandNode(categories, string.Empty);

            var category1 = categories.ChildNodes[0];
            var category2 = categories.ChildNodes[1];

            model.ExpandNode(category1, string.Empty);

            var item1 = category1.ChildNodes[0];
            var item2 = category1.ChildNodes[1];
            var item3 = category1.ChildNodes[2];
            var item4 = category1.ChildNodes[3];
            var item5 = category1.ChildNodes[4];

            model.ExpandNode(item1, string.Empty);

            var description = item1.ChildNodes[0];

            model.ExpandNode(description, string.Empty);

            var descriptionText = description.ChildNodes[0];

            Assert.IsNotNull(descriptionText);
        }
        #endregion

        #region ModifyTextNodeAction tests
        [TestMethod()]
        public void ModifyTextNodeActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, string.Empty);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ExpandNode(categories, string.Empty);

            var category1 = categories.ChildNodes[0];
            var category2 = categories.ChildNodes[1];

            model.ExpandNode(category1, string.Empty);

            var item1 = category1.ChildNodes[0];
            var item2 = category1.ChildNodes[1];
            var item3 = category1.ChildNodes[2];
            var item4 = category1.ChildNodes[3];
            var item5 = category1.ChildNodes[4];

            model.ExpandNode(item1, string.Empty);

            var description = item1.ChildNodes[0];

            model.ExpandNode(description, string.Empty);

            var descriptionText = description.ChildNodes[0] as BigXmlNodeInternal;

            Assert.IsNotNull(descriptionText);

            Assert.AreEqual<string>("Item 1", descriptionText.XmlNode.CreateNavigator().Value);

            Assert.IsFalse(model.Modified);
            model.ModifyTextNode(descriptionText, "New Item 1");
            Assert.IsTrue(model.Modified);
            Assert.IsTrue(descriptionText.Modified);

            Assert.AreEqual<string>("New Item 1", descriptionText.XmlNode.CreateNavigator().Value);

            string rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(@"<root>
  <categories>
    <category>
      <item>
        <description>New Item 1</description>
      </item>
      <item />
      <item />
      <item />
      <item />
    </category>
    <category />
  </categories>
  <stock />
</root>", rawXml);

            model.Undo();

            Assert.IsFalse(descriptionText.Modified);

            Assert.AreEqual<string>("Item 1", descriptionText.XmlNode.CreateNavigator().Value);
            rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(@"<root>
  <categories>
    <category>
      <item>
        <description>Item 1</description>
      </item>
      <item />
      <item />
      <item />
      <item />
    </category>
    <category />
  </categories>
  <stock />
</root>", rawXml);

            model.Redo();

            Assert.IsTrue(descriptionText.Modified);

            Assert.AreEqual<string>("New Item 1", descriptionText.XmlNode.CreateNavigator().Value);
            rawXml = model.GetRawXml();

            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
            Assert.AreEqual<string>(@"<root>
  <categories>
    <category>
      <item>
        <description>New Item 1</description>
      </item>
      <item />
      <item />
      <item />
      <item />
    </category>
    <category />
  </categories>
  <stock />
</root>", rawXml);
        }

        [TestMethod()]
        public void ModifyTextNodeActionEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);
            var categories = root.ChildNodes[0];
            model.ExpandNode(categories);
            var category = categories.ChildNodes[0];
            model.ExpandNode(category);
            var item = category.ChildNodes[0];
            model.ExpandNode(item);
            var description = item.ChildNodes[0];
            model.ExpandNode(description);
            var text = description.ChildNodes[0];

            Action test = () => {
                model.ModifyTextNode(text, "New Text");
            };

            var expectedSequence = new[] { "Modified", "NodeUpdated", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region OriginalAddress tests
        [TestMethod()]
        public void OriginalAddressTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            Assert.IsTrue(root.Address.SequenceEqual(root.OriginalAddress));

            model.ExpandNode(root, string.Empty);
            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            model.ChangeNodeOrder(categories, stock);

            Assert.IsTrue(stock.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 2 }));

            Assert.IsTrue(stock.OriginalAddress.SequenceEqual(new int[] { 1, 2 }));
            Assert.IsTrue(categories.OriginalAddress.SequenceEqual(new int[] { 1, 1 }));

            model.ExpandNode(categories, string.Empty);

            Assert.AreEqual<int>(2, categories.ChildNodes.Count);

            var category1 = categories.ChildNodes[0];
            var category2 = categories.ChildNodes[1];

            string xml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
        }
        #endregion

        #region Save tests
        [TestMethod]
        public void SaveTest01() {
            var model = ModelFactory.CreateXmlModel();

            string newPath = Common.PathTest6 + ".tmp";
            File.Copy(Common.PathTest6, newPath);
            model.Open(newPath);

            var root = model.GetRootElement();
            Assert.IsFalse(model.Modified);
            model.RenameElement(root, "newRootElement");
            Assert.IsTrue(model.Modified);
            model.Save(false);
            Assert.IsFalse(model.Modified);

            Assert.IsFalse(model.CanUndo);

            model.RenameElement(root, "newRootElement2");
            Assert.IsTrue(model.Modified);

            Assert.IsTrue(model.CanUndo);

            model.Save(false);
            Assert.IsFalse(model.Modified);

            Assert.IsTrue(newPath.FileCompare(newPath + ".Correct"));
        }

        [TestMethod]
        public void SaveEventsTest() {
            var model = ModelFactory.CreateXmlModel();

            string newPath = Common.PathTest6 + ".tmp2";
            File.Copy(Common.PathTest6, newPath);
            model.Open(newPath);

            var root = model.GetRootElement();
            Assert.IsFalse(model.Modified);
            model.RenameElement(root, "newRootElement");
            Assert.IsTrue(model.Modified);

            Action test = () => model.Save(false);

            var expectedSequence = new[] { "Saving", "Path", "Saved", "Modified", "SaveCompleted" };
            EventMonitor.Assert(test, model, expectedSequence);

        }
        #endregion

        #region UpdateAttributes tests
        [TestMethod]
        public void UpdateAttributesTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);

            var root = model.GetRootElement();

            model.ExpandNode(root);

            var oldTestament = root.ChildNodes[0];
            var newTestament = root.ChildNodes[1];

            var attributes = new Dictionary<string, IBigXmlAttribute> { { ":test:", new BigXmlAttribute("test", "value") }, { ":value:", new BigXmlAttribute("value", "staryZakon") } };

            Assert.IsFalse(model.Modified);
            model.UpdateAttributes(oldTestament, attributes);
            Assert.IsTrue(model.Modified);

            Assert.AreEqual<int>(2, oldTestament.Attributes.Count);

            model.Undo();

            Assert.IsFalse(model.Modified);
            Assert.AreEqual<int>(1, oldTestament.Attributes.Count);
        }
        #endregion

        #region GetChildNodes from xmlModel tests
        /// <summary>
        /// Test for TotalChildCount from GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodesTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement();

            Assert.AreEqual<int>(2, root.TotalChildCount);
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void GetChildNodesTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest7);

            var root = model.GetRootElement();
            Assert.AreEqual<int>(7, root.TotalChildCount);

            model.ExpandNode(root);
            var child6 = root.ChildNodes[5];
            Assert.AreEqual<int>(1, child6.TotalChildCount);

            var child7 = root.ChildNodes[6];
            Assert.AreEqual<int>(3, child7.TotalChildCount);

            model.ExpandNode(child7);

            Assert.AreEqual<int>(3, child7.ChildNodes.Count);
            var emptyElement = child7.ChildNodes[1];
            Assert.AreEqual<int>(0, emptyElement.TotalChildCount);

            model.ExpandNode(emptyElement);
        }
        #endregion

        #region ExpandAll tests
        [TestMethod()]
        public void ExpandAllEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();
            model.ExpandNode(root);

            Action test = () => {
                model.ExpandAll();
            };

            var expectedSequence = new[] { "NodeExpanded", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod()]
        public void ExpandAllTest01() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            model.ExpandAll();
            var root = model.GetRootElement();

            Assert.IsTrue(root.NodeState == ExpandState.Expanded);
            Assert.AreEqual<int>(37, model.Nodes.Count);
        }
        #endregion

        #region Close
        [TestMethod()]
        public void CloseEventsTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            Action test = () => {
                model.Close();
            };

            var expectedSequence = new[] { "Closing", "Closed" };
            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region Open
        [TestMethod]
        [ExpectedException(typeof(FileNotFoundException))]
        public void OpenTest01() {
            var model = ModelFactory.CreateXmlModel("nonexistentfile.xml");
        }

        [TestMethod]
        public void OpenEventsTest() {
            var model = ModelFactory.CreateXmlModel();

            Action test = () => model.Open(Common.PathTest1);

            var expectedSequence = new[] { "Path" };
            EventMonitor.Assert(test, model, expectedSequence);

            test = () => {
                model.Open(Common.PathTest1);
            };

            expectedSequence = new[] { "Path" };
            EventMonitor.Assert(test, model, expectedSequence);

            test = () => {
                model.Open(Common.PathTest1);
            };

            expectedSequence = new[] { "Path" };
            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod]
        public void OpenTest02() {
            var model = ModelFactory.CreateXmlModel() as IXmlModelWithNotifications;
            model.Open(Common.PathTsmt);

            Assert.IsTrue(model.DocumentType != null);
        }
        #endregion

        #region Add & remove nodes (from dictionary) tests
        /// <summary>
        /// GetRootElement
        /// </summary>
        [TestMethod()]
        public void DictionaryTest01() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            Assert.AreEqual<int>(0, model.Nodes.Count);
            var root = model.GetRootElement() as BigXmlNodeInternal;
            Assert.AreEqual<int>(1, model.Nodes.Count);
            Assert.IsTrue(model.Nodes.Contains(new KeyValuePair<IXPathNavigable, BigXmlNodeInternal>(root.XmlNode, root)));
        }

        /// <summary>
        /// Expand & collapse param.
        /// </summary>
        [TestMethod()]
        public void DictionaryTest02() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.AreEqual<int>(3, model.Nodes.Count);
            Assert.IsTrue(model.Nodes.ContainsKey(categories.XmlNode));
            Assert.IsTrue(model.Nodes.ContainsKey(stock.XmlNode));

            model.CollapseNode(root);
            Assert.AreEqual<int>(1, model.Nodes.Count);
        }

        /// <summary>
        /// Expand and collapse param.
        /// </summary>
        [TestMethod()]
        public void DictionaryTest03() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, "1");
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;

            Assert.AreEqual<int>(2, model.Nodes.Count);
            Assert.IsTrue(model.Nodes.ContainsKey(categories.XmlNode));

            model.CollapseNode(root);
            Assert.AreEqual<int>(1, model.Nodes.Count);
        }

        /// <summary>
        /// Expand and collapse param.
        /// </summary>
        [TestMethod()]
        public void DictionaryTest04() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root, "2");
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.AreEqual<int>(2, model.Nodes.Count);
            Assert.IsTrue(model.Nodes.ContainsKey(stock.XmlNode));

            model.CollapseNode(root);
            Assert.AreEqual<int>(1, model.Nodes.Count);
        }

        /// <summary>
        /// Add chiild param & undo.
        /// </summary>
        [TestMethod()]
        public void DictionaryTest05() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            var newNode = model.CreateElement("newNode") as BigXmlNodeInternal;
            model.AddChildNode(root, newNode, InsertMode.Last, null);

            Assert.AreEqual<int>(4, model.Nodes.Count);
            Assert.IsTrue(model.Nodes.ContainsKey(newNode.XmlNode));

            model.Undo();

            Assert.AreEqual<int>(3, model.Nodes.Count);
        }

        /// <summary>
        /// Remove child param & undo
        /// </summary>
        [TestMethod()]
        public void DictionaryTest06() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();

            model.ExpandNode(root);
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.AreEqual<int>(3, model.Nodes.Count);
            model.RemoveNode(categories, true);
            Assert.AreEqual<int>(2, model.Nodes.Count);

            model.Undo();

            Assert.AreEqual<int>(3, model.Nodes.Count);
        }

        /// <summary>
        /// CreateRootElement
        /// </summary>
        [TestMethod()]
        public void DictionaryTest07() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;

            model.CreateRootElement("root");
            var root = model.GetRootElement() as BigXmlNodeInternal;

            Assert.AreEqual<int>(1, model.Nodes.Count);

            model.Undo();
            Assert.AreEqual<int>(0, model.Nodes.Count);
        }

        /// <summary>
        /// ChangeNodeOrder
        /// </summary>
        [TestMethod()]
        public void DictionaryTest08() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);
            var categories = root.ChildNodes[0] as BigXmlNodeInternal;
            var stock = root.ChildNodes[1] as BigXmlNodeInternal;

            Assert.AreEqual<int>(3, model.Nodes.Count);

            model.ChangeNodeOrder(categories, stock);

            Assert.AreEqual<int>(3, model.Nodes.Count);

            model.Undo();

            Assert.AreEqual<int>(3, model.Nodes.Count);
        }

        /// <summary>
        /// Expand all.
        /// </summary>
        [TestMethod()]
        public void DictionaryTest09() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            model.ExpandAll();
            var root = model.GetRootElement();

            Assert.AreEqual<int>(37, model.Nodes.Count);

            model.CollapseNode(root);
            Assert.AreEqual<int>(1, model.Nodes.Count);
        }
        #endregion

        #region Select nodes tests
        [TestMethod()]
        public void SelectNodesTest01() {
            var model = ModelFactory.CreateXmlModel() as XmlModel;
            model.Open(Common.PathTest1);

            model.ExpandAll();
            var root = model.GetRootElement();

            var selectedNodes = model.SelectNodesCore("//item", root as BigXmlNodeInternal);
            Assert.IsNotNull(selectedNodes);
            Assert.AreEqual<int>(6, selectedNodes.Count());
        }
        #endregion

        #region MoveSubtreeAction tests
        /// <summary>
        /// Basic test for MoveSubtree action.
        /// </summary>
        [TestMethod]
        public void MoveSubtreeActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            model.MoveSubtree(categories, stock, InsertMode.Last, null);

            Assert.AreEqual<int>(1, root.TotalChildCount);
            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 1, 3 }));
            Assert.IsTrue(categories.Parent == stock);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <stock>
    <books />
    <cds />
    <categories />
  </stock>
</root>", xml);

            Assert.IsTrue(categories.Modified);
            Assert.IsTrue(stock.Modified);

            model.Undo();

            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.IsTrue(categories.Address.SequenceEqual(new int[] { 1, 1 }));
            Assert.IsTrue(categories.Parent == root);

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.IsFalse(categories.Modified);
            Assert.IsFalse(stock.Modified);

            model.ExpandNode(categories, string.Empty, true);

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories>
    <category>
      <item>
        <description>Item 1</description>
      </item>
      <item>
        <description>Item 2</description>
      </item>
      <item>
        <description>Item 3</description>
      </item>
      <item>
        <description>Item 4</description>
      </item>
      <item>
        <description>Item 5</description>
      </item>
    </category>
    <category>
      <item>
        <description>Item 6</description>
      </item>
    </category>
  </categories>
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        [TestMethod()]
        public void MoveSubtreeActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            var books = stock.ChildNodes[0];

            model.MoveSubtree(categories, stock, InsertMode.After, books);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <stock>
    <books />
    <categories />
    <cds />
  </stock>
</root>", xml);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        [TestMethod]
        public void MoveSubtreeActionTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            var books = stock.ChildNodes[0];
            var cds = stock.ChildNodes[1];

            model.MoveSubtree(categories, stock, InsertMode.Before, cds);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <stock>
    <books />
    <categories />
    <cds />
  </stock>
</root>", xml);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        [TestMethod()]
        public void MoveSubtreeActionTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            model.MoveSubtree(categories, stock, InsertMode.First, null);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <stock>
    <categories />
    <books />
    <cds />
  </stock>
</root>", xml);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);
        }

        [TestMethod()]
        public void MoveSubtreeActionTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            Action test = () => model.MoveSubtree(categories, stock, InsertMode.First, null);

            var expectedSequence = new[] { "Modified", "SubtreeUpdated", "SubtreeUpdated", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);

            test = () => {
                model.Undo();
            };

            EventMonitor.Assert(test, model, expectedSequence);
        }
        #endregion

        #region CopySubtreeAction tests
        /// <summary>
        /// Basic test for CopySubtree action.
        /// </summary>
        [TestMethod]
        public void CopySubtreeActionTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            Assert.AreEqual<int>(2, stock.TotalChildCount);
            Assert.AreEqual<int>(5, model.NodeCount);

            model.CopySubtree(categories, stock, InsertMode.Last, null);

            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.AreEqual<int>(3, stock.TotalChildCount);
            Assert.AreEqual<int>(6, model.NodeCount);

            Assert.IsTrue(categories.Parent == root);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
    <categories />
  </stock>
</root>", xml);

            Assert.IsTrue(stock.Modified);
            Assert.IsTrue(stock.ChildNodes[2].Modified);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.AreEqual<int>(5, model.NodeCount);
        }

        [TestMethod]
        public void CopySubtreeActionTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            Assert.AreEqual<int>(2, stock.TotalChildCount);

            //xmlModel.CopySubtree(categories, stock, InsertMode.Last, null);
            //var action = new CopySubtreeAction(xmlModel, categories, stock, InsertMode.Last, null);
            var copy = CopySubtreeAction.CopySubtree(categories as BigXmlNodeInternal);

            var categoriesInternal = categories as BigXmlNodeInternal;
            Assert.AreNotEqual(copy, categoriesInternal);
            Assert.AreNotEqual(copy.XmlNode, categoriesInternal.XmlNode);
            Assert.AreNotEqual(copy.Parent, categoriesInternal.Parent);
            Assert.IsNull(copy.Parent);
            Assert.AreNotEqual(copy.Address, categoriesInternal.Address);
            Assert.AreNotEqual(copy.OriginalAddress, categoriesInternal.OriginalAddress);
            Assert.IsTrue(copy.Address.SequenceEqual(categoriesInternal.Address));
        }

        [TestMethod]
        public void CopySubtreeActionTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            Action test = () => {
                model.CopySubtree(categories, stock, InsertMode.Last, null);
            };

            var expectedSequence = new[] { "Modified", "SubtreeUpdated", "RawXmlChanged" };
            EventMonitor.Assert(test, model, expectedSequence);

            test = () => {
                model.Undo();
            };

            EventMonitor.Assert(test, model, expectedSequence);
        }

        [TestMethod]
        public void CopySubtreeActionTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);

            Assert.AreEqual<int>(2, stock.TotalChildCount);
            Assert.AreEqual<int>(5, model.NodeCount);

            model.CopySubtree(categories, stock, InsertMode.First, null);

            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.AreEqual<int>(3, stock.TotalChildCount);
            Assert.AreEqual<int>(6, model.NodeCount);

            Assert.IsTrue(categories.Parent == root);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <categories />
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.IsTrue(stock.Modified);
            Assert.IsTrue(stock.ChildNodes[0].Modified);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.AreEqual<int>(5, model.NodeCount);
        }

        [TestMethod]
        public void CopySubtreeActionTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            var cds = stock.ChildNodes[1];

            Assert.AreEqual<int>(2, stock.TotalChildCount);
            Assert.AreEqual<int>(5, model.NodeCount);

            model.CopySubtree(categories, stock, InsertMode.Before, cds);

            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.AreEqual<int>(3, stock.TotalChildCount);
            Assert.AreEqual<int>(6, model.NodeCount);

            Assert.IsTrue(categories.Parent == root);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <categories />
    <cds />
  </stock>
</root>", xml);

            Assert.IsTrue(stock.Modified);
            Assert.IsTrue(stock.ChildNodes[0].Modified);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.AreEqual<int>(5, model.NodeCount);
        }

        [TestMethod]
        public void CopySubtreeActionTest06() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement();
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];
            model.ExpandNode(stock);
            var books = stock.ChildNodes[0];

            Assert.AreEqual<int>(2, stock.TotalChildCount);
            Assert.AreEqual<int>(5, model.NodeCount);

            model.CopySubtree(categories, stock, InsertMode.After, books);

            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.AreEqual<int>(3, stock.TotalChildCount);
            Assert.AreEqual<int>(6, model.NodeCount);

            Assert.IsTrue(categories.Parent == root);

            var xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <categories />
    <cds />
  </stock>
</root>", xml);

            Assert.IsTrue(stock.Modified);
            Assert.IsTrue(stock.ChildNodes[0].Modified);

            model.Undo();

            xml = model.GetRawXml();
            Assert.AreEqual<string>(@"<root>
  <categories />
  <stock>
    <books />
    <cds />
  </stock>
</root>", xml);

            Assert.AreEqual<int>(5, model.NodeCount);
        }
        #endregion

        #region VerifyAddress tests
        [TestMethod]
        public void VerifyAddressTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTsmt);

            var root = model.GetRootElement();
            model.ExpandNode(root);
            var coverpg = root.ChildNodes[0];
            var titlepg = root.ChildNodes[1];
            var preface = root.ChildNodes[2];
            var bookcoll = root.ChildNodes[3];

            Assert.IsTrue(coverpg.OriginalAddress.SequenceEqual(new[] { 1, 1 }));
            Assert.IsTrue(titlepg.OriginalAddress.SequenceEqual(new[] { 1, 2 }));
            Assert.IsTrue(preface.OriginalAddress.SequenceEqual(new[] { 1, 3 }));
            Assert.IsTrue(bookcoll.OriginalAddress.SequenceEqual(new[] { 1, 4 }));

            model.ChangeNodeOrder(coverpg, titlepg);

            Assert.IsTrue(coverpg.OriginalAddress.SequenceEqual(new[] { 1, 1 }));
            Assert.IsTrue(titlepg.OriginalAddress.SequenceEqual(new[] { 1, 2 }));
            Assert.IsTrue(preface.OriginalAddress.SequenceEqual(new[] { 1, 3 }));
            Assert.IsTrue(bookcoll.OriginalAddress.SequenceEqual(new[] { 1, 4 }));

            model.ValidateDtd();

            Assert.IsTrue(coverpg.OriginalAddress.SequenceEqual(new[] { 1, 1 }));
            Assert.IsTrue(titlepg.OriginalAddress.SequenceEqual(new[] { 1, 2 }));
            Assert.IsTrue(preface.OriginalAddress.SequenceEqual(new[] { 1, 3 }));
            Assert.IsTrue(bookcoll.OriginalAddress.SequenceEqual(new[] { 1, 4 }));
        }
        #endregion

        #region SetDocumentType tests
        [TestMethod]
        public void SetDocumentTypeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            Assert.IsNull(model.DocumentType);

            model.SetDocumentType("root", null, "tstmt.dtd", null);

            Assert.IsNotNull(model.DocumentType);
            Assert.AreEqual<string>("root", model.DocumentType.Name);
            Assert.IsNull(model.DocumentType.PublicId);
            Assert.AreEqual<string>("tstmt.dtd", model.DocumentType.SystemId);
            Assert.IsNull(model.DocumentType.InternalSubset);
        }

        [TestMethod]
        public void SetDocumentTypeTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            Assert.IsNull(model.DocumentType);

            model.SetDocumentType("root", null, "tstmt.dtd", null);

            Assert.IsNotNull(model.DocumentType);

            model.Undo();

            Assert.IsNull(model.DocumentType);

            model.Redo();

            Assert.IsNotNull(model.DocumentType);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetDocumentTypeTest03() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.SetDocumentType(null, null, null, null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void SetDocumentTypeTest04() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.SetDocumentType("", "", "", "");
        }

        [TestMethod]
        public void SetDocumentTypeTest05() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.SetDocumentType("root", null, null, null);
            var rawXml = model.GetRawXml();
            Assert.IsTrue(!string.IsNullOrEmpty(rawXml));
        }

        [TestMethod]
        [ExpectedException(typeof(FileNotFoundException))]
        public void SetDocumentTypeTest06() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            model.SetDocumentType("root", null, "nonexistent.dtd", null);
        }
        #endregion

        #region RemoveDocumentTypeAction tests
        [TestMethod]
        public void RemoveDocumentTypeTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTsmt);
            Assert.IsNotNull(model.DocumentType);

            model.RemoveDocumentType();
            Assert.IsNull(model.DocumentType);
        }
        #endregion

        #region ChildCount
        [TestMethod]
        public void ChildCountTest01() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathBible1);
            var root = model.GetRootElement();

            var count = model.CountNodes(root.Address);
            Assert.AreEqual(63464, count);

            count = model.CountNodes(new int[] { 1, 1 });
            Assert.AreEqual(47261, count);

            count = model.CountNodes(new int[] { 1, 2 });
            Assert.AreEqual(16202, count);
        }

        [TestMethod]
        public void ChildCountTest02() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);
            var root = model.GetRootElement();

            var count = model.CountNodes(root.Address);
            Assert.AreEqual(37, count);

            count = model.CountNodes(new int[] { 1, 1 });
            Assert.AreEqual(21, count);

            count = model.CountNodes(new int[] { 1, 2 });
            Assert.AreEqual(15, count);

            count = model.CountNodes(new int[] { 1, 1, 1, 1 });
            Assert.AreEqual(3, count);
        }
        #endregion
    }
}